前言:
最重要的还是最后的流程图,可以试着根据流程图手写实现$().on(),下篇文章会放出模拟实现的代码。

一、举例

<div id="A" style="background-color: deeppink">  这是A

    <div id="C" style="background-color: aqua">    这是C    </div>

</div>

  $("#A").on("click" ,function (event) {    console.log(event,"A被点击了")  })

  $("#A").on("click" ,"#C",function (event) {    console.log(event,"点击了C,即C委托A的click事件被点击了")  })复制代码

二、$().on()
(1)进行参数的调整
(2)调用jQuery.event.add()方法

三、jQuery.event.add()最终调用elem.addEventListener()来绑定事件
注意:
(1)绑定常用的事件(如:click、focus),使用handleObj保存

handleObj = jQuery.extend( {          //click,mouseout...          type: type,          //click,mouseout...          origType: origType,          data: data,          //事件处理函数,如 function(){console.log('aaaa')}          handler: handler,          //索引,用于关联元素和事件          guid: handler.guid,          //事件委托的标志,也是委托的对象选择器          selector: selector,          needsContext: selector && jQuery.expr.match.needsContext.test( selector ),          //命名空间,同一click事件有两个事件处理程序handler的话,          //用这个标识,方便删除或添加handler          namespace: namespaces.join( "." )        }, handleObjIn );复制代码

(2)如果绑定的是自定义事件(如:windowResize),则使用handleObjIn保存

if ( handler.handler ) {   handleObjIn = handler;   handler = handleObjIn.handler;   selector = handleObjIn.selector;}复制代码

(1)、(2)都会初始化事件处理器(addEventListener):

        //第一次绑定事件,走这里        // Init the event handler queue if we're the first        if ( !( handlers = events[ type ] ) ) {          handlers = events[ type ] = [];          handlers.delegateCount = 0;          // Only use addEventListener if the special events handler returns false          if ( !special.setup ||            special.setup.call( elem, data, namespaces, eventHandle ) === false ) {            //目标元素有addEventListener的话,调用绑定click事件            //eventHandle就绑定到addEventListener上            if ( elem.addEventListener ) {              elem.addEventListener( type, eventHandle );            }          }        }复制代码

四、jQuery的事件绑定为何不直接绑定在目标元素身上,而是元素和事件分离?
打印$("#A")

console.log($("#A"),'aaaaaa46')复制代码

不要在意jQueryId不同的问题,每次刷新网页它都会变化

可以看到

jQuery的事件和触发事件的handler是分离的,
事件集合 存在 事件缓存dataPrivevents上,

//获取数据缓存elemData = dataPriv.get( elem );复制代码

而handler是由jQuery.event.dispatch()处理

elemData.handle = function( e ) {  jQuery.event.dispatch.apply( elem, arguments )}复制代码

为什么要分离?因为元素如果绑定click事件一百次,很耗内存。所以需要将这一百个同类型的事件保存到一个click事件集合中,然后在这一大个click事件集合内,根据guid来执行某一次的click处理代码

同一事件的处理:

$('body').on('click', '#one', function(e) {  show('委托到one触发')})$('body').on('click', '#two', function(e) {  show('委托到two触发')})复制代码

events是jQuery内部的事件队列
handle是真正绑定到element上的事件处理函数

body:{  events:{    click:[      0:{        guid: 1,        data: undefined,        namespace: "",        origType: "click",        //事件委托的标志        selector: "#one",        type: "click",        handler: function(){xxx},        }      1:{        guid: 2,        data: undefined,        namespace: "",        origType: "click",        //事件委托的标志        selector: "#two",        type: "click",        handler: function(){xxx},        }    ]  },  handle: function(){    jQuery.event.dispatch.apply( elem, arguments )  }}复制代码

可以看到,针对同一类型的事件(如click),重复绑定不会再创建新的内存(new Object会有新内存),而是在events里添加新的绑定事件。

记得看第十一点!

五、guid的作用?
添加guid的目的是因为handler没有直接跟元素节点发生关联,所以需要一个索引来寻找或者删除handler

六、命名空间namespace的作用?

 $("#one").on("click.one",function () {   console.log("one被点击了") }) $("#one").on("click.two",function () {   console.log("two被点击了") })复制代码

命名空间为:

#one:{  events:{    click:[      0:{        namespace: "one",        handler: function(){console.log("one被点击了")},        }      1:{        namespace: "two",        handler: function(){xxx},        }    ]  },}复制代码

利用命名空间删除事件:

$("#one").off("click.one")复制代码

七、jQuery.event.special 的处理机制
绑定的事件,有些是不能统一处理的,比如load事件,是不支持冒泡的,所以即使开发者未用event.stopPropagation,jQuery也要阻止其冒泡:

jQuery.event ={  special: {    load: {        // Prevent triggered image.load events from bubbling to window.load        //阻止冒泡        noBubble: true    },    focus: {        // Fire native event if possible so blur/focus sequence is correct        trigger: function() { },        delegateType: "focusin"    },  }}复制代码

八、外部是Event,内部是数据缓存events,两者是不一样的
外部Event:

$().on("click","#B",function(event){  console.log("A被点击了")})

//click的event就是jQuery.EventjQuery.Event{  handleObj{    data:undefined,    guid: 2,    handler:function(){console.log("A被点击了")},    namespace: "clickA",    origType: "click",    selector: "#B",    type: "click.clickA",  },  originalEvent:{    //就是MouseEvent  },  target:div#B,  type: "click",  delegateTarget: div#A,  //fix 的标志  jQuery331087940272164138: true,  currentTarget: div#A,  isDefaultPrevented:xxx,  timeStamp:Date.now(),  isDefaultPrevented:function(){return false}}复制代码

内部缓存events:

let events = dataPriv.get( this, "events" )

events[    delegantCount:1,   {      data:undefined,      guid: 2,      handler:function(){console.log("B委托A被点击了")},      namespace: "clickA",      origType: "click",      selector: "#B",      type: "click.clickA",    },   {     data:undefined,      guid: 1,      handler:function(){console.log("A被点击了")},      namespace: "",      origType: "click",      selector: undefined,      type: "click",    }   

]复制代码

九、为什么要使用fix()来重构 js 的原生 MouseEvent 对象呢?
(1)jQuery 有自己的一套event处理机制,所以需要符合jQueryevent对象
(2)可以传递 data 数据,即用户自定义的数据。

十、trigger的触发机制

  $("#A").on("click" ,function (event) {    console.log(event,"A被点击了")  })复制代码

元素#A本身绑定了一个click事件,但是click是原生事件,它是靠 addEventListener绑定来触发事件的。

但是!jQuerytrigger是能够无差别模拟这个交互行为的

$("#A").trigger("click")复制代码

trigger()的功能上就可以解释 为什么jQuery要设计元素与数据分离了:

如果是直接绑定的话就无法通过trigger的机制去触发click事件,
正是因为jQuery没有直接把事件相关的handler与元素直接绑定,而是采用了分离处理,
所以我们通过trigger触发click事件与addEventListener触发click事件的处理流程是一致的,不同的只是触发的方式而已。

但是,通trigger触发的事件是没有事件对象(event)、冒泡(bubble)这些特性的,所以我们需要有一个功能 能模拟出事件对象,然后生成一个遍历树(eventPath)模拟出冒泡行为,这个就交给了trigger方法了

关于$().trigger()的源码解析请看:jQuery源码解析之trigger()


最后,附上自己做的 jQuery事件绑定到触发全过程的流程图:


(完)

转载于:https://juejin.im/post/5d077ff0e51d45773d46860e

jQuery之事件绑定到触发全过程及知识点补充相关推荐

  1. jQuery的事件绑定和解绑

    1.绑定事件 语法: bind(type,data,fn) 描述:为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数. 参数解释: type (String) : 事件类型 data ( ...

  2. jQuery得事件绑定

    1. 绑定事件 语法 bind(type,data,fn) 描述:为每一个匹配元素得特定事件绑定一个事件处理器函数. 参数解释: type:事件类型 data:作为event.data属性值传递给事件 ...

  3. HTML——jQuery之事件绑定、取消事件绑定及事件委托

    事件绑定 事件绑定有两种方法:分别是:.click() 和.on() <!DOCTYPE html> <html lang="en"> <head&g ...

  4. jQuery之事件绑定

    bind() 方法为被选元素添加一个或多个事件处理程序,并规定事件发生时运行的函数. 下面是具体的用法: <script type="text/javascript"> ...

  5. 【Babylon小技巧04】进阶双开门事件绑定同时触发

    鼠标点击其中一扇门时,另外一扇也同时开启或关闭 效果如图 双开门playground地址: Babylon.js Playgroundhttps://playground.babylonjs.com/ ...

  6. jQuery jq事件绑定

    jQuery已经很多年没有更新过了,因此ES6新增的一些事件和箭头函数等,它是不支持的

  7. java mvc jquery weui_WEUI 事件绑定

    1.**简易的输入同步框** 所需用到的事件为bindinput,详情可以查看[开发文档][Link 1] > 通过bindinput事件来监听输入框的值是否发生改变且获取到改变后的值,之后在j ...

  8. jQuery文本框(input textare)事件绑定方法教程

    jquery 的事件绑定已经用on替换了原来的bind,接下来为大家分享下bind的使用方法及input textare事件.目前1.7以上,jquery?的事件绑定已经用on替换了原来的bind,接 ...

  9. 【源码小记】jQueryの事件绑定

    前言 这篇笔记很大的帮助来源于慕课网上jQuery源码解读课程,虽然jQuery现在已经慢慢衰退了,但是作为一个学习者,我自己还是很愿意去琢磨琢磨其中的原理.如果有错误欢迎指出,谢谢了^0^. 事件绑 ...

最新文章

  1. Koa2框架从0开始构建预告片网站
  2. 极光推送 java api_JPush极光推送Java服务器端API
  3. 2.4. myisamchk — MyISAM Table-Maintenance Utility
  4. Spring Boot @Transactional 配置事务管理
  5. 微信造梦西游服务器错误,造梦西游ol常见问题解答
  6. nodejs后台系列--第三篇-最简单的全栈demo:koa2+mysql+vue
  7. html 滑动门效果,js实现简洁的滑动门菜单(选项卡)效果代码
  8. 【每日更新】万维钢精英日课3课程分享笔记:模糊逻辑:灰度认知,灰度决策,黑白执行
  9. 国家区域代码关系整理
  10. 01-12.产品经理入门到精通(一)
  11. crm系统哪家公司做的最好?企业如何选择crm供应商
  12. MySql的基石——索引
  13. 【本科课程学习】数据库考试复习题(带答案)
  14. 跟我学springboot(十五)springboot日志选型
  15. OpenCV中HSV与PS中HSB对应关系
  16. win怎么在计算机里按日期搜索文件,Win8系统如何按指定修改日期搜索文件
  17. AI 投资探索路上的一些感受
  18. ffmpeg音频视频转换命令笔记
  19. 安排 , 2021新冠疫情防控指挥作战平台(视频+课件+代码+资料)
  20. html5 拍照 苹果手机黑屏,苹果手机拍照黑屏怎么办?iphone拍照黑屏的解决办法...

热门文章

  1. mysql+last_query_cost_辛星简译MySQL中的last_query_cost
  2. python 文件批量转换格式_python实现快速文件格式批量转换的方法
  3. linux搜索文件中包含的字符
  4. Linux 下mysql操作
  5. Linux排查java程序CPU占用过高问题
  6. mysql存储php数组_mysql数据库存储PHP数组、对象的方法
  7. 动画会震一下css,csshake.css强大的CSS3元素抖动动画库
  8. php接口模式,PHP设计模式 - 流接口模式
  9. kafka是什么_Kafka为什么快到根本停不下来?
  10. java+cache使用方法_JVM代码缓存区CodeCache原理及用法解析