React事件简介React事件是一个合成事件,所有事件都自动绑定到最外层。因为VirtualDOM在内存中是以对象的形式存在的,React在VirtualDOM的基础上实现了一个SyntheticEvent(合成事件)层,我们定义的事件处理器会接收一个SyntheticEvent对象的实例。支持事件冒泡机制,我们可以使用stopPropagation()和preventDefault()来中断它。没有兼容性问题。事件绑定?事件绑定方式和原生事件绑定类似,但是事件的属性名(比如onClick)必须用驼峰写法;React并没有像DOM0级事件那样直接将事件处理器绑定到HTML元素上,而是一个函数指针:buttononclick="handleClick()">Test//dom0测试合成事件的实现机制在React的底层,主要是为合成事件做两件事:事件委托和自动绑定。1.事件委托React并没有直接将事件处理程序绑定到真实的节点上,而是将所有的事件绑定到结构的最外层,使用一个统一的事件监听器,它维护一个映射来保存所有组件内部的事件监听器和处理程序。当组件挂载或卸载时,只是在这个统一的事件监听器上插入或删除一些对象;当一个事件发生时,首先被这个统一的事件监听器处理,然后在map中找到真正的事件处理函数并调用它。这样简化了事件处理和回收机制,效率大大提高。2、自动绑定在React组件中,每个方法的上下文都会指向该组件的实例,即自动将this绑定为当前组件。但是在使用ES6类或者纯函数的时候,需要手动实现this的绑定。具体有以下几种方法:1.通过bind方法实现;每次重新渲染都会生成一个新的函数实例保存在listenerBank中,浪费内存。render(){//通过bind方法实现,可以传参returnTest;}render(){//When不传递任何参数,您也可以使用::而不是returnTest;}2"在构造函数中使用bind绑定,不需要每次调用都绑定。推荐importReact,{Component}from'react';类App扩展组件{constructor(props){super(props);this.handleClick=this.handleClick.bind(this);}handleClick(e){console.log(e);}render(){return测试;}}3》ArrowfunctionclassAppextendsComponent{//不能带参数consthandleClick=(e)=>{console.log(e);};render(){return测试;}}classAppextendsComponent{//每次渲染都会生成一个新的函数实例handleClick(e){console.log(e);}render(){returnthis.handleClick()}>Test}}React合成事件与JavaScript原生事件对比在React合成事件的场景中,我们还需要使用本机事件完成。从4个方面对比React合成事件和JavaScript原生事件。1.事件传播和防止事件传播浏览器原生DOM事件的传播可以分为3个阶段:事件捕获阶段、目标对象自身的事件处理器调用、事件冒泡。当e.addEventListener()的第三个参数设置为true时,可以为事件注册捕获阶段,但是ie9不支持,所以没有意义。React只提供了事件冒泡机制,通过e.prevent-Default()。需要使用e.preventDefault()来阻止native事件传播,但是对于不支持该方法的浏览器(IE9以下),只能使用e.cancelBubble=true来阻止。2.事件类型React合成事件的事件类型是JavaScript原生事件类型的一个子集。3.事件绑定方式受DOM标准影响,绑定浏览器原生事件的方式有很多种,如下图。1》在DOM元素中直接绑定:Test2》在JavaScript中,通过给元素的event属性赋值实现绑定:el.onclick=e=>{console.log(e);}3》绑定是通过事件监听函数实现的:el.addEventListener('click',()=>{},false);el.attachEvent('onclick',()=>{});相比之下,React合成事件的绑定方法就简单多了:Test4.事件对象原生DOM事件对象在W3C标准下和IE标准下有区别,在较低的IE浏览器版本,只能通过window.event获取事件对象,在React合成事件系统中不存在兼容性问题,可以在事件处理函数中获取合成事件对象。