章节
问答
课签
笔记
评论
占位
占位

on的绑定机制

我们通过 on 接口绑定一个事件的时候,内部做了一些比较复杂的处理:

主要针对几个设计问题的处理:

  1. 针对同一个对象的多个相同/不同的事件如何处理?
  2. 命名空间的处理?
  3. 自定义事件是如何触发的?
  4. 全局事件如何出发?

具体很多问题我们在后续课程中会一个一个解决,我们先看看如果同一个元素绑定多个相同或者不同的事件要如何处理?

首先我们脑海中先要有一个分离的概念,jQuery 的事件与数据其实是没有直接关联的关系,而且通过数据缓存去存储事件数据的。jQuery 从1.2.3版本引入数据缓存系统贯穿内部,为整个服务事件体系也引入了这个缓存机制,所以 jQuery 并没有将事件处理函数直接绑定到 DOM 元素上,而是通过 .data 存储在缓存 .cahce 上,所以事件的机制都是依赖之前的数据缓存模块的。

我们为了理解 jQuery.event.add 代码结构,适当的跳过这个环节中不能理解的代码。

第一步:获取数据缓存

//获取数据缓存
elemData = data_priv.get( elem );

通过缓存对象的 get 方法获取元素对应的存储数据,如果没有则内部会新建一个与 elem 元素映射的数据缓存区,用来存储之后用户将要要处理操作行为(事件与事件),这个处理主要是合并同个元素绑定多个事件的问题。

aaron.on('mousedown', 'li', function(e) {
  show('委托到li触发')
})
aaron.on('mousedown', 'ul', function(e) {
  show('委托到ul触发')
})
aaron.on('mousedown', 'div', function(e) {
  show('委托到div触发')
})
aaron.on('mousedown', function(e) {
  show('mousedown')
})

如上同一个元素上绑定了 4 次不同的行为,但是都是针对同一个元素的所以这个地方我们就需要把事件与数据都合并到同一个缓存区,这样每次重复操作都不会在去创建一个新的缓存了。

第二步:创建编号

if( !handler.guid ) {               
 handler.guid= jQuery.guid++;           
}

为每一个事件的句柄给一个标示,添加 ID 的目的是用来寻找或者删除 handler,因为这个东东是缓存在缓存对象上的,没有直接跟元素节点发生关联。

第三步:给缓存增加事件处理句柄

if ( !(events = elemData.events) ) {
    events = elemData.events= {};
}
if ( !(eventHandle = elemData.handle) ) {
    eventHandle = elemData.handle = function( e ) {
        return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
            jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
            undefined;
    };
}

events,eventHandle 都是 elemData 缓存对象内部的,可见在elemData中有两个重要的属性:

  1. 一个是 events,是jQuery内部维护的事件列队
  2. 一个是 handle,是实际绑定到elem中的事件处理函数

之后的代码无非就是对这 2 个对象的筛选、分组、填充了。

第四步: 填充事件名与事件句柄

事件名称可以添加指定的 event namespaces(命名空间) 来简化删除或触发事件。例如,"click.myPlugin.simple" 为 click 事件同时定义了两个命名空间 myPlugin 和 simple。通过上述方法绑定的 click 事件处理,可以用 .off("click.myPlugin").off("click.simple") 删除绑定到相应元素的 Click 事件处理程序,而不会干扰其他绑定在该元素上的“click(点击)” 事件。命名空间类似 CSS 类,因为它们是不分层次的;只需要有一个名字相匹配即可。以下划线开头的名字空间是供 jQuery 使用的。所以要针对每个事件都需要绑定。

如:

.on('mouseup mousedown','p',function(e){
    console.log(e)
  })

其实就是填充events与eventHandle

elemData = {
       events:{}
       eventHandle:function(){}
}
handlers = events[type] = [];
handlers.delegateCount = 0;

这段比较长了分解下,最终的目的就是为填充events,eventHandle。

其实整个 add 方法下来就干了那么几件事:

  1. 利用 data_priv 数据缓存,分离事件与数据
  2. 元素与缓存中建立 guid 的映射关系用于查找
  3. 通过 elemData.events 合并同一个元素上的多个事件
  4. 通过空格分隔的多事件
  5. 引用了钩子处理特殊事件
  6. 如果委托元素,给对应的数据打上一个记录标记
  7. 最后通过 addEventListener 绑定事件,等待执行

所以我们可以看到在绑定的时候处理,都是为了后期做了大量的铺垫。

任务

?不会了怎么办
||

提问题

写笔记

公开笔记
提交
||

请验证,完成请求

由于请求次数过多,请先验证,完成再次请求

加群二维码

打开微信扫码自动绑定

您还未绑定服务号

绑定后可得到

  • · 粉丝专属优惠福利
  • · 大咖直播交流干货
  • · 课程更新,问题答复提醒
  • · 账号支付安全提醒

收藏课程后,能更快找到我哦~

使用 Ctrl+D 可将课程添加到书签

邀请您关注公众号
关注后,及时获悉本课程动态

举报

0/150
提交
取消
全部 精华 我要发布
全部 我要发布
最热 最新
只看我的

手记推荐

更多

本次提问将花费2个积分

你的积分不足,无法发表

为什么扣积分?

本次提问将花费2个积分

继续发表请点击 "确定"

为什么扣积分?