jquery 监听td点击事件_React 事件 | 1. React 中的事件委托
说到 React 的事件,也算是 React 的一个非常有亮点的优化,它在原生事件体系的基础上,单独实现了一套事件机制。想要了解这个机制,首先的了解下什么是事件委托以及事件委托的好处。
事件委托
假设有如下 html,我们想要在每个 li 上绑定 onClick 事件,最直观的做法当然就是给每个 li 分别添加事件,增加事件回调。这种做法当然没错,但是我们有一种更好的做法,那就是在 ul 上添加有个监听事件,由于事件的冒泡机制,事件就会冒泡到ul上,因为ul上有事件监听,所以事件就会触发。
Event 对象提供了一个属性叫 target,可以返回事件的目标节点,我们成为事件源,也就是说,target 就可以表示为触发当前的事件 dom,我们可以根据 dom 进行判断到底是哪个元素触发了事件,根据不同的元素,执行不同的回调方法。
这就是事件委托。
<
事件委托有以下优点。
- 减少事件注册,节省内存,能够提升整体性能。
- 简化了dom节点更新时,相应事件的更新(用过 jquery 的都知道,动态加入的元素,事件需要重新绑定)。
React 数据结构
React 并不是将 click 事件直接绑定在 dom 上面,而是采用事件冒泡的形式冒泡到 document 上面,这个思路借鉴了事件委托机制。所以,React 中所有的事件最后都是被委托到了 document这个顶级 DOM 上。
这个事件委托是在什么时候完成的呢?我们看如下示例。
<
这就是一个普通的 div,经过 React 的处理后,render 中的内容会变成以下数据结构。
{
React 会根据这个数据结构来构造真实的 dom,如果对之前的内容还有印象,我们在创建 HostComponent,也就是原生节点的时候,会调用 ensureListeningTo(rootContainerElement, propKey) 这个方法。
function
ensureListeningTo 就是用来完成事件委托的,对于本例来说,rootContainerElement 表示项目挂载的根节点 div,registrationName 就是我们绑定事件的名称 onClick。div 的 nodeType 是ELEMENT_NODE,也就是元素节点,那么会通过该元素的 ownerDocument 属性获得文档的 Document 对象,然后将 onClick 事件挂载到 Document 对象上。
了解了这点后,我们先不看 listenTo 方法,回过头来了解下 React 事件的整理流程。
React 事件流程
react 源码中有一个注释很好的总结了 React 的事件流程(在注释中画流程图,很社会)。
react-domsrceventsReactBrowserEventEmitter.js
/**
从这个图可以看出,Dom 事件发生后,React 通过事件委托机制将大部分事件代理至 Document 层,ReactEventListener 就是负责给元素绑定事件的。ReactEventEmitter 暴露接口给 React 组件层用于添加事件订阅(对外暴露了 listenTo 等方法)。EventPluginHub 负责管理和注册各种插件。在事件分发时,调用插件来生成合成事件。 React 事件系统使用了插件机制来管理不同行为的事件。这些插件会处理自己感兴趣的事件类型,并生成合成事件对象。
比如 SimpleEventPlugin 负责处理一些比较通用的事件类型,如blur、focus、click、submit、touchMove、mouseMove、scroll、drag、load。
EnterLeaveEventPlugin 负责处理 mouseEnter/mouseLeave 和 pointerEnter/pointerLeave 这两类事件,单独处理的原因是这两类事件不支持冒泡。
TapEventPlugin 是为了解决移动端IOS 300ms 点击延迟,该插件增加了一个 onTouchTap 事件,这个事件触发后,会忽略300ms 后的 onClick 事件。
这里还需要了解的是,EventPluginHub 中处理的时间其实是合成事件 (SyntheticEvent),React 为什么要定义合成事件这个概念呢,有三点原因:
- 合成事件 (SyntheticEvent) 可以认为是浏览器原生事件跨浏览器的封装,相当于 React 帮我们做了浏览器的兼容性处理。
- React 想通过 SyntheticEvent 实现跨平台事件机制。
- 原生事件升级、改造,比如 React 的 onChange 事件,它为表单元素定义了统一的值变动事件,例如 blur、change、focus、input 等。
React 事件委托
了解了 React 大概的事件体系后,接着看之前的 ensureListeningTo 方法,该方法总调用了 listenTo 方法,这个方法就是 ReactEventEmitter 中的(对应着上面的图看会清晰很多)。
react-domsrceventsReactBrowserEventEmitter.js
export
我们看下 registrationNameDependencies 的数据结构。registrationNameDependencies 比较多,我们看些熟悉的。registrationNameDependencies 存放的是 React 事件名与原生事件名映射的 Map。可以很明显的看到,有些事件是合成事件,比如 onBeforeInput,onChange 等。onClick 事件就是原生的 click。这些值都是插件赋予的。
{
对于依赖的原生事件,scroll blur focus cancel close 方法注册捕获阶段的事件监听器。invalid submit reset 事件不做处理。剩下的事件需要判断是否是媒体触发的,比如 video / audio 的 onplaying 事件,onprogress 事件, onratechange 事件等,这些媒体事件也不需要处理。
React 这么做的原因和事件有关,有些事件是不冒泡的,所以不能在冒泡阶段进行事件委托。具体情况请看我的另一篇文章“JavaScript那些不会冒泡的事件”,大家可以先去了解下这些不会冒泡的事件,回头看 React 的处理流程会比较清晰。
上述代码中处理了个特殊的情况,那就是 form 的 submit invalid,reset 事件,这几个事件没有委托给 Document 对象,如下所示。
case
为什么呢?原因是如果将 submit 事件绑定到 Form 上,该事件的监听方法会触发两次。当提交按钮被点击后,事件开始冒泡,当冒泡到 Form 的上的时候,由于 Form 存在 onSubmit 回调,会执行一次,然后向上冒泡到 Document,还会执行一次。所以 React 对于 Form 事件就不做处理了。
<
React 同样也没有处理媒体事件,和 Form 事件不同的是,媒体事件是没有冒泡过程的,所以只能在捕获阶段进行事件委托。
<
经过测试后发现,媒体事件如果在捕获阶段进行事件委托,该事件的回调方法会被执行两次,和 Form 的表现是一致的,所以媒体事件没有委托。
除了上述的特殊事件,剩下的事件执行 trapBubbledEvent,也就是注册冒泡阶段的事件监听器,click 事件当然也处在这个行列。
trapBubbledEvent 和 trapCapturedEvent 大同小异,本例中触发的 click 事件属于冒泡事件,我们分析 trapBubbledEvent 方法。
react-domsrceventsReactDOMEventListener.js
export
trapBubbledEvent 调用 trapEventForPluginEventSystem 方法
function
React 中的事件分为 3 类。分别是 DiscreteEvent(离散事件),UserBlockingEvent(用户阻塞事件),ContinuousEvent(连续事件)。不同类型的事件代表了不同的优先级。
- DiscreteEvent:click,blur,focus,submit,tuchStart 等,优先级是 0。
- UserBlockingEvent:touchMove,mouseMove,scroll,drag,dragOver 等,这些事件会阻塞用户的交互,优先级是 1。
- ContinuousEvent:load,error,loadStart,abort,animationend 等,优先级是 2,这个优先级最高,不会被打断。
根据优先级的不同,监听函数做了不同的包装,我们先不管这里生成的监听函数和最初的监听方法有什么不同。最终我们会调用 addEventBubbleListener 方法。
addEventBubbleListener 就是 element.addEventListener,为目标添加事件监听函数。
export
到此为止,一个事件 click 事件的监听方法就被添加到 Document 对象上了。小结一下:
- React 借鉴事件委托的方式将大部分事件委托给了 Document 对象。
- React 中的事件分为 3 类。分别是 DiscreteEvent(离散事件),UserBlockingEvent(用户阻塞事件),ContinuousEvent(连续事件)。不同类型的事件代表了不同的优先级。
- 事件委托需要区分捕获和冒泡,有些事件由于没有冒泡过程,只能在捕获阶段进行事件委托。
- 没有进行委托的事件是 Form 事件和 Media 事件,原因是这些事件委托后会触发两次回调函数。
建议先阅读我的另一篇文章JavaScript 中那些不会冒泡的事件,这样会更容易理解 React 对于事件的处理过程
如果您觉得有所收获,就麻烦点个赞吧!
jquery 监听td点击事件_React 事件 | 1. React 中的事件委托相关推荐
- jquery 监听td点击事件_安卓开发监听点击事件的一种方法
本人是菜鸟一只,学习安卓纯属兴趣.没有真正上过编程课程,所有知识都是在网上获取的.今天分享的是监听点击事件的一个方法,这个方法的好处是代码较简洁. 如图,点击保存时,把上面的数据入库. 实现如下: 在 ...
- jquery 监听td点击事件_VUE @hook浅析(监听子组件的生命周期钩子) - 古兰精
一.前言 接触hook是从webhook开始接触的,webhook是git的一个扩展服务,可以在仓库接收到push/commit事件并发送http request至一个开发者可以自定义的URL.通过这 ...
- jquery监听窗口大小改变事件jquery.resizeend
方法一: $(function(){// Bind the resize event. When any test element's size changes, update its// corre ...
- Jquery监听onChange事件
Jquery监听onChange事件 $(document).ready(function () {$("#控件ID").change(function () {var organ ...
- 综合设计一个OPPE主页--页面的插件引用(animate.css)--d动画的使用--滚轮或鼠标到该位置时,才有动画的切换---所以我们需要用jquery监听鼠标滚轮的滚动事件
Animate.css | A cross-browser library of CSS animations. 里面有许多css的效果 首先使用 animate.css文件 link rel=&qu ...
- maptalks常见操作——图层置顶置底、添加清空图层、添加标注、切换底图、添加缩放工具、事件监听(点击面出弹框)、右键菜单、绘制mark、锁定视角
maptalks常见操作--图层置顶置底.添加清空图层.添加标注.切换底图.添加缩放工具.事件监听(点击面出弹框).右键菜单.绘制mark.锁定视角 1.图层置顶 置底 layer.show().br ...
- 监听当点击微信等app的返回按钮或者浏览器的上一页或后退按钮的事件
在实际的应用中,我们常常需要实现在移动app和浏览器中点击返回.后退.上一页等按钮实现自己的关闭页面.调整到指定页面或执行一些其它操作的 需求,那在代码中怎样监听当点击微信.支付宝.百度糯米.百度钱包 ...
- jQuery 监听修改文本框事件
在开发中,有时我们需要对 input 的 value 值变化作实时响应.比如文本输入框的实时字数统计功能,要求文本框内容改变时就要触发相关的统计行为.不管这个内容是键盘输入的,还是鼠标粘贴进来的.1, ...
- 使用swipecard实现卡片视图左右滑动监听以及点击监听
使用swipecard实现卡片视图左右滑动监听以及点击监听 前言: 大家好,今天给大家介绍安卓一种特别实用有很酷炫的组件swipecard,当然这并不是安卓爸爸创造的,这是国内的一个我认为是大牛的一 ...
最新文章
- 美国在理论计算机科学的研究重视,留学热门专业计算机之研究方向篇
- AppleScript 以管理员身份运行程序
- (59)Verilog HDL测试激励:时钟激励1
- 20211027:《Labuladong的算法小抄》学习记录(一)
- 通过表名导出DDL语句(包含建表、索引、注释、主键)
- linux QT 结束当前进程_Linux桌面进化史
- EAS后台事务的超时时长如何设置?
- 奇怪的键盘按a截图了
- HBuilder快捷键整理集合
- 新闻分析:微软到底需要雅虎什么?
- (完结)Unity游戏开发——新发教你做游戏(七):Animator控制角色动画播放
- 常用eclips快捷键小结
- 你应该看得懂的RecyclerView嵌套
- 华为OD机试 - 高矮个子排队
- C语言字符串中‘\0‘问题
- php手册学习记录(入门指引处理表单)
- 【淘宝SEO】搜索诊断助手新增作弊检测
- 天猫精灵java开发工程师工资_李双印-天猫精灵2020年校招(对话系统方向)
- 你认为喜剧演员何欢什么时候会走红?
- Zotero | 快速入门
热门文章
- [附源码]JAVA+ssm明天摄影工作室(程序+Lw)
- 魔兽怀旧服联盟服务器不稳定,魔兽世界怀旧服上次被联盟攻击至少三个月前,“单边服”何去何从...
- 手把手教你安装 illustrator(Ai)2022 软件
- 和平精英android怎么写符号,和平精英名字符号如何输入 名字符号输入方法
- Java操作Cookie之添加Cookie
- python c++情侣网名是什么意思_c++中嵌入python 看什么意思
- 做IT喝刺五加,健康!
- 小黑leetcode之旅:86. 分隔链表
- smb.conf 详解
- lisp 删除编组中图元_2013-09-05 明经 AutoLISP 编程(102918348) 群聊记录:删除列表中第N个元素是用哪个函数?vl-remove 是把列表里相同都会删掉...