react自身实现了一套自己的事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等,虽然和原生的是两码事,但也是基于浏览器的事件机制下完成的。
react 的所有事件并没有绑定到具体的dom节点上而是绑定在了document 上,然后由统一的事件处理程序来处理,同时也是基于浏览器的事件机制(冒泡),所有节点的事件都会在 document 上触发。
React事件与原生事件的执行顺序又是如何?
代码示例
import React from 'react';
class App extends React。Component {
constructor(props) {
super(props);
this.parentRef = React.createRef();
this.childRef = React.createRef();
}
componentDidMount() {
console.log('react componentDidMount');
this.parentRef.current?.addEventListener('click', () => {
console.log('父元素:原生事件 父元素 DOM 事件监听');
});
this.childRef.current?.addEventListener('click', () => {
console.log('子元素:原生事件 子元素 DOM 事件监听');
});
document.addEnvetListener('click', e => {
console.log('document:原生document DOM 事件监听');
});
}
parentClickFun = () => {
console.log('React:父元素事件监听');
};
childClickFun = () => {
console.log('React:子元素事件监听');
}
render() {
return (
<div ref={this.parentRef} onClick={this.parentClickFun}>
<div ref={this.childRef} onClick={this.childClickFun}>事件执行</div>
</div>
);
}
}
输出:
子元素:原生事件 子元素 DOM 事件监听
父元素:原生事件 父元素 DOM 事件监听
React:子元素事件监听
React:父元素事件监听
document:原生document DOM 事件监听
事件执行顺序:
1、先执行 子元素的DOM事件
2、执行 父元素的DOM事件
3、执行 React 子元素的事件
4、执行 React 父元素的事件
5、 最后执行 document上的DOM事件的监听
由上总结:
1、React 中所有事件都挂载在document对象上
2、先触发真是DOM事件,再触发React事件
3、最后执行document 上挂载的事件
如何阻止冒泡行为?
1、阻止合成事件的冒泡, e.stopPropagation();
2、阻止合成事件与最外层document 上的事件的冒泡:e.nativeEvent.stop
3、阻止合成事件与原生事件的冒泡:
document.body.addEventListener('click', e => {
if (e.target && e.target.matches('div.code')) {
return;
}
this.setState({active: false});
});
总结
React 最终会绑定在document这个DOM上
React有一套自己的合成事件机制