通过一道题来看React事件模型

发布时间:2024-01-25 08:30

下面代码输出什么

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 (
    
事件执行顺序
); };

执行结果:

  • 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上的事件

更多可以查看下面提到的文章

参考

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号