通过一道题来看React事件模型
下面代码输出什么
const MainApp = () => {
const parentRef = useRef();
const childRef = useRef();
const parentClickFun = useCallback(() => {
console.log('react parent');
}, []);
const childClickFun = useCallback(() => {
console.log('react child');
}, []);
useEffect(() => {
document.addEventListener('click', () => {
console.log('document');
});
parentRef.current?.addEventListener('click', () => {
console.log('dom parent');
});
childRef.current?.addEventListener('click', () => {
console.log('dom child');
});
}, []);
return (
<div ref={parentRef} onClick={parentClickFun}>
<div ref={childRef} onClick={childClickFun}>
事件执行顺序
</div>
</div>
);
};执行结果:
dom child
dom parent
react child
react parent
document代码分析
主要是考察 React 合成事件和 JS 原生事件的区别,以及它们的执行顺序。以React16.x版本之前的来分析。React16.x 以后有变更。
分析一下上面的代码:可以分成两部分来看,JS原生事件部分及React合成事件部分。
- useEffect 里面都是直接通过 addEventListener 做的事件绑定,如果addEventListener 不指定第二个参数的话,默认是冒泡阶段执行。所以 useEffect里的执行顺序 dom child, dom parent, document
- 再来看 parentClickFun, childClickFun 这两个函数是通过 React 的事件去绑定的。React 利用事件委托机制在 document 上统一监听DOM事件,再根据触发的target将事件分发到具体的组件实例。React 自己实现了一套冒泡机制。所以这部分的执行顺序为:react child,react parent
最后来理解一下整个的执行顺序。
- react中的所有事件都是挂载到document上的
- 当真实 dom 触发冒泡到 document 后才会对react事件进行处理
- 所以JS原生事件会先执行
- 然后执行React的合成事件
- 最后执行真正挂载到 document上的事件
来自:https://segmentfault.com/a/1190000042005939
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!