美文网首页
react的事件委托机制

react的事件委托机制

作者: 指尖跳动 | 来源:发表于2020-03-11 23:34 被阅读0次

在开始之前,可以先看一下另一篇关于dom本身的事件机制《谈谈js点击之后发生了什么》

前言

如果你有试过输出react事件中的event,你就会发现这个event好像和我们看到的dom事件中的event不太一样,那是因为react在进行dom事件绑定时,不是直接绑定事件的,而是通过所谓的合成事件(SyntheticEvent)进行委托管理的,它是原生事件进行封装后的结果,你可以通过nativeEvent获取原生事件。

通过例子观察

class App extends Component {
  componentDidMount(){
    document.addEventListener('click', function(){
      console.log('document click')
    })
    document.getElementsByClassName('App')[0].addEventListener('click', function(){
      console.log('app click')
    })
    document.getElementsByTagName('button')[0].addEventListener('click', function(e){
      console.log('button click')
      // e.stopPropagation();
    })
  } 
  onClick = (e) => {
    e.stopPropagation() // 能够阻止div.app的触发
    e.nativeEvent.stopImmediatePropagation(); // 能够阻止document的触发
    e.nativeEvent.stopPropagation(); // 什么都阻止不了
    console.log('react button click');
  };
  render() {
    return (
      <div className="App" onClick={() => {console.log('react app click')}}>
        <button onClick={this.onClick}>按钮</button>
      </div>
    );
  }
}

我们在用react绑定了两个事件,同时在didmount给真实dom也绑定了事件,点击button之后的执行顺序是

button click
app click
react button click
react app click
document click

原理

react并不是我之前所设想的将事件绑定在真实dom上,而是通过自己的事件处理器来处理,将所有的事件都绑定在document上,这样真实点击的时候,冒泡到document上,react再通过document去dispatchEvent统一处理事件

所以上面的stopPropagation就能理解了,e.stopPropagation只能阻止虚拟dom的事件冒泡,但它本身是由document触发的,所以e.nativeEvent.stopPropagation什么也阻止不了,document就是冒泡的顶点,e.nativeEvent.stopImmediatePropagation可以阻止document的事件,这和它本身有关

需要注意的是react在生成真实的dom节点会加入一些东西帮助事件分发

dom节点的react属性(15和16有点区别)


react15
react16

15和16会有一点细微的区别,具体什么还没有去了解,但是看来对事件的影响不大,15是有一个__rootNodeID来区分组件,16是通过__debugID来区分,如果理解上有错误,欢迎指正哦

  • vdom
// 简化
let vdom = {
  type: 'div',
  props: {
    onClick: function(){
      console.log('react app click')    
    },
    children: [
      {
        type: 'button',
        props: {
           onClick: function() {
              console.log('react button click')    
           }
        }
      }
    ]
  }
}
  • 注册事件
let bankForRegistrationName = {}; // 回调事件的保存
// react构建真实dom树
...
// 注册事件
bankForRegistrationName = {
    // 数字是_debugID,react用于识别每一个dom
    5: {
      click: function(){
        console.log('react app click')    
      },
    },
    6: {
      click: function(){
        console.log('react button click')    
      },
    }
}
  • 事件触发
// 合成事件简单实现
function SyntheticEvent(e) {
  ...
  this.nativeEvent = e;
  ...
}
// e: event, type: 事件类型
function dispatchEvent(e, type) {
  let synE = new SyntheticEvent(e);
  // 执行监听事件
  let debugID = e.target.__reactInternalInstance$om8tco7dvl._debugID;
  bankForRegistrationName[debugID][type](synE); 
}
// document事件委托
document.addEventListener('click', function(e) {
  dispatchEvent(e, 'click');
})

总结

基本上就是这样了(当然没有对冒泡做处理,react会遍历自己的vdom去执行冒泡)

  1. 事件管理中心(bankForRegistrationName)会在react-render过程中保存所有所有dom事件
  2. document作为事件委托者,用来分发事件(dispatchEvent),通过dom节点唯一标识(_debugID)去事件管理(bankForRegistrationName)触发事件

from:https://www.jianshu.com/p/b249793fd2a7

相关文章

  • React学习之漫谈React

    事件系统 合成事件的绑定方式 Test 合成事件的实现机制:事件委派和自动绑定。 React合成事件系统的委托机制...

  • react的事件委托机制

    在开始之前,可以先看一下另一篇关于dom本身的事件机制《谈谈js点击之后发生了什么》 前言 如果你有试过输出rea...

  • 事件委托笔记

    事件委托原理:事件冒泡机制。 什么是事件委托: 事件委托——给父元素绑定事件,用来监听子元素的冒泡事件,并找到是哪...

  • --

    react事件机制 react基于浏览器原生事件机制,封装了一套自己的事件机制,包括事件注册、事件合成、冒泡和捕获...

  • react源码分析(3):react的事件委托机制

    在开始之前,可以先看一下我的另一篇关于dom本身的事件机制《谈谈js点击之后发生了什么》 前言 如果你有试过输出r...

  • 事件委托

    事件委托 事件委托其实就是利用JS事件冒泡机制把原本需要绑定在子元素的响应事件(click、keydown……)委...

  • 【React进阶系列】史上最全React事件机制详解

    框架总览 ? DOM事件流的三个阶段 ? 关于React事件的疑问? React事件绑定机制? React事件和原...

  • 总结.Net基础知识——献给即将入坑的同行们(二期)

    事件是不是一种委托? 委托是一种安全的函数指针,事件是一种消息机制 委托与事件是什么关系?为什么要使用委托 委托提...

  • js的事件委托机制

    什么是事件委托?为什么要用事件委托? 事件委托机制又叫事件代理.我们给dom绑定一个事件往往很简单 可是如果给一个...

  • Unity3d-c#-观察者设计模式-猫抓老鼠

    在这个例子中运用了委托事件机制讲述了事件和委托的区别最大的区别是:事件是特殊的受限的委托,事件只能在类内部调用,不...

网友评论

      本文标题:react的事件委托机制

      本文链接:https://www.haomeiwen.com/subject/dxnkjhtx.html