React 合成事件是 React 模拟原生 DOM 事件所有能力的一个对象,它根据 W3C规范来定义合成事件,兼容所有浏览器,拥有与浏览器原生事件相同的接口。
react官方描述分别打印出合成事件对象e和原生对象e.nativeEvent
//
function enqueuePutListener(inst, registrationName, listener, transaction) {
...
var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;
1. 找到document
var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
2. 注册事件,将事件注册到document上
3. listenTo(registrationName, doc);
存储事件,放入事务队列中
}
react事件系统内部对事件在不同浏览器上的执行做了兼容因此无需使用者考虑浏览器相关情况:
listen: function listen(target, eventType, callback) {
if (target.addEventListener) {
将原生事件添加到target这个dom上,也就是上边传递的document上
这就是只有document这个DOM节点上有原生事件的原因
target.addEventListener(eventType, callback, false);
...
} else if (target.attachEvent) {
target.attachEvent('on' + eventType, callback);
...
}
}
function handleTopLevelImpl(bookKeeping) {
1. 找到事件触发的DOM和React Component
var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);
var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget);
2. 执行事件回调前,先由当前组件向上遍历它的所有父组件。
得到ancestors这个数组,这个数组同时也是冒泡顺序。
var ancestor = targetInst;
do {
bookKeeping.ancestors.push(ancestor);
ancestor = ancestor && findParent(ancestor);
} while (ancestor);
这个顺序就是冒泡的顺序,并且我们发现不能通过stopPropagation来阻止'冒泡'。
for (var i = 0; i < bookKeeping.ancestors.length; i++) {
targetInst = bookKeeping.ancestors[i];
ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
}
}
1. 初始化时将eventPlugin注册到EventPluginHub中,不同plugin分别构造不同类型的合成事件
ReactInjection.EventPluginHub.injectEventPluginsByName({
...不同插件
});
2. 将事件放入事件池:
EventPluginHub.enqueueEvents(events);
3. 再处理队列中的事件,包括之前未处理完的:
EventPluginHub.processEventQueue(false);
刚接触react的同学,往往在react事件使用时会与原生事件混合(这里并非指责这种混用行为,只是在混用阶段需要区分出react时间系统和js本身事件的执行差异),时常会有事件执行出现不符合预期的情况,这里我们用一个小demo来感受下二者执行的差异:打印出执行结果:
react事件集中在document上集中管理
react事件队列的存储和取出使用缓解了dom元素注册销毁所消耗的性能
e.persist()
//可以阻止事件池清掉取出事件https://github.com/facebook/react/: https://github.com/facebook/react/
[2]React 17 要来了,非常特别的一版 - 梦烬 - 博客园: https://www.cnblogs.com/ayqy/p/react-17.html
以上便是本次分享的全部内容,希望对你有所帮助^_^
喜欢的话别忘了 分享、点赞、收藏 三连哦~。
欢迎关注公众号 ELab团队 收货大厂一手好文章~
我们来自字节跳动,是旗下大力教育前端部门,负责字节跳动教育全线产品前端开发工作。
我们围绕产品品质提升、开发效率、创意与前沿技术等方向沉淀与传播专业知识及案例,为业界贡献经验价值。包括但不限于性能监控、组件库、多端技术、Serverless、可视化搭建、音视频、人工智能、产品设计与营销等内容。
欢迎感兴趣的同学扫描下方二维码 内推到文章作者部门 拍砖 🤪