(提示:一个没有添加过点击事件的真实DOM元素,被点击了也会有事件冒泡) React事件都注册在document中,DOM被点击了就会冒泡到document中,然后document会结合虚拟dom树,找到那个事件进行调用,在document中使用事件委托的方式进行
这里的事件是 React内置组件的事件(就像是原生div的那些onclick,input的onchange、onblur) (如果给每一个元素都注册事件,那就会注册很多很多个事件,所以他用如下的做法)
React事件
- 给document注册事件(因为事件都会冒泡到document所以直接监听document)
- 几乎所有的元素的事件处理,均在document的事件中处理
a. 对于一些不会冒泡的事件还是在React元素上监听的(对于这种元素的话阻止真实dom的冒泡事件的话就是没有用的) b. 一些document没有的事件,直接在React元素上监听(例如video的onPlay事件) - 在document的事件处理,React会根据虚拟dom树的结构完成事件函数的调用
- React的事件参数,并非一个真实DOM事件参数,他是React合成的对象,该对象类似于真实DOM的事件参数
1 . e.stopPropagation,阻止事件在虚拟DOM中的冒泡 2 . e.nativeEvent,可以得到真实的DOM事件对象 3 . 为了提高执行效率,React使用事件对象池来处理事件对象(当对象池未满时,React 创建新的事件对象,派发给组件。当对象池装满时,React 从池中复用事件对象,派发给组件)
(先会运行document的事件,然后才会运行react注册的事件,因为react是在document注册的事件,当一个react事件被触发了就会冒泡,最终冒泡到document然后在由document触发那个react事件,然后react事件也会冒泡到上面的react元素)
注意事项
● 如果阻止了根节点的冒泡事件这样React的事件就不会运行了(因为document就监听不到React事件的调用了) ● 给真实的DOM元素注册事件都会先于React元素的事件执行(document事件委托) ● 通过React的事件中阻止事件冒泡,无法阻止真实的DOM事件(因为真实DOM都已经都冒泡到document了,再阻止也没有了,而且React元素的事件参数e不是一个真实DOM的事件参数e) ● 可以通过nativeEvent.stopImmediatePropagation(),阻止document上剩余事件的执行(和其他库配合之后的时候有可能用到,用来阻止其他库的事件执行) ● React的事件参数会被服用一个React用完之后会把事件参数重新赋值成null,等下一个事件用的事件就直接赋值就行,所以不要异步的使用React的事件参数(如果要异步使用React的事件参数就要使用e.persist()使这个事件参数持久化,这样就会浪费性能)
|