从一个bug说起
下面这个demo_13在react17和react16中有什么不同吗?代码也很简单,模拟一个modal框,点击显示出现,点击其他地方,相当于点击了mask,modal消失,因为react事件都是委托到上层,所以需要在handleClick阻止冒泡,这样点击显示的时候不会触发document上的事件回调,导致modal无法显示。但是在react16上发现这样做还是不行,需要调用e.nativeEvent.stopImmediatePropagation()才能实现,而react17上没什么影响
究其原因就是react16和17在委托事件的容器上做出了改变,react16的事件会冒泡的document上,而17则会冒泡到root容器上,也就是ReactDom.render的第二个参数
export default class Demo13 extends React.Component {
state = {
show: false };
componentDidMount() {
document.addEventListener("click", () => {
this.setState({
show: false });
});
}
handleClick = (e) => {
e.stopPropagation();//react17中生效
// e.nativeEvent.stopImmediatePropagation(); //react16中生效 stopImmediatePropagation也阻止本级监听函数执行
this.setState({
show: true });
};
render() {
return (
<div>
<button onClick={
this.handleClick}>显示</button>
{
this.state.show && <div onClick={
(e) => e.nativeEvent.stopImmediatePropagation()}>modal</div>}
</div>
);
}
}
大家也可以看下demo_11、demo_12在react16、17触发顺序有何差异,同时demo项目中的event.html也模拟了react16、17的事件代理机制
事件系统架构图
我们以SimpleEvent为例看事件注册、绑定和触发的过程,看视频的调试过程
事件注册
- DOMPluginEventSystem.js会调用SimpleEventPlugin插件的registerEvents方法注册事件,
//DOMPluginEventSystem.js
SimpleEventPlugin.registerEvents();
- registerSimpleEvents
function registerSimpleEvents