当前位置: 首页 > Web前端 > HTML5

jQuery的事件势必触发全流程知识点补充

时间:2023-04-05 22:19:33 HTML5

前言:最重要的是最后的流程图,大家可以根据流程图手写尝试实现$().on(),并且下篇文章会放出一个仿真实现代码。1.例子>$("#A").on("click",function(event){console.log(event,"Awasclicked")})$("#A").on("click","#C",function(event){console.log(event,"C被点击,即C委托A点击的点击事件")})二、$().on()(1)调整参数(2)调用jQuery.event.add()方法3.jQuery.event.add()最后调用elem.addEventListener()绑定事件注意:(1)绑定普通事件(如:点击,焦点),使用handleObj保存handleObj=jQuery.extend({//click,mouseout...type:type,//click,mouseout...origType:origType,data:data,//事件处理函数,如function(){console.log('aaaa')}handler:handler,//索引,用来关联元素和事件guid:handler.guid,//事件委托的标志,也是委托选择器的对象选择器:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),//命名空间,如果同一个点击事件有两个事件处理器,//使用这个标签公认的,易于删除或添加处理程序命名空间:namespaces.join(".")},handleObjIn);(2)如果绑定的是自定义事件(如:windowResize),使用handleObjIn保存if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector;}(1),(2)会初始化事件处理器(addEventListener)://第一次绑定事件,到这里//如果我们是第一个则初始化事件处理器队列if(!(handlers=events[type])){handlers=events[type]=[];handlers.delegateCount=0;//只有在特殊事件处理程序返回false时才使用addEventListenerif(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){//如果目标元素有addEventListener,调用并绑定点击事件//eventHandle绑定到addEventListener}}}四、为什么jQuery的事件绑定不是直接绑定到目标元素上,而是从元素和事件中分离出来的?打印$("#A")console.log($("#A"),'aaaaaa46')不用管jQueryId的不同,每次刷新网页都会变,可以看到jQuery事件和触发事件的handler是分开,事件集合有事件缓存在dataPriv的事件上,//获取数据缓存elemData=dataPriv.get(elem);并且处理程序由jQuery.event.dispatch()处理elemData.handle=function(e){jQuery.event.dispatch.apply(elem,arguments)}为什么分开?因为如果一个元素绑定click事件一百次,会消耗大量内存所以需要将这一百个同类型的事件保存在一个点击事件集合中,然后在这个庞大的点击事件集合中,根据guid执行一定的点击处理代码来处理同一个事件:$('body').on('click','#one',function(e){show('delegatetoonetrigger')})$('body').on('click','#two',function(e){show('delegatedtotwotrigger')})events是jQuery里面的事件队列handle是实际绑定到元素body上的事件处理函数:{events:{click:[0:{guid:1,data:undefined,namespace:"",origType:"click",//事件委托符号选择器:"#one",type:"click",handler:function(){xxx},}1:{guid:2,data:undefined,namespace:"",origType:"click",//事件委托符号选择器:"#two",type:"click",handler:function(){xxx},}]},handle:function(){jQuery.event.dispatch.apply(elem,arguments)}}可以看到对于同一类型的事件(比如点击),重复绑定不会产生新的内存(新的Object会有新的内存),而是在事件中添加新的绑定事件。记得看第十一点!五、guid的作用?添加guid的目的是因为handler与元素节点没有直接关联,所以需要一个索引来查找或删除handler六、命名空间namespace的作用?$("#one").on("click.one",function(){console.log("onewasclicked")})$("#one").on("click.two",function(){console.log("twowasclicked")})命名空间是:#one:{events:{click:[0:{namespace:"one",handler:function(){console.log("onewasclicked")},}1:{namespace:"two",handler:function(){xxx},}]},}使用命名空间删除事件:$("#one").off("click.one")7、jQuery.event.special的处理机制绑定的一些事件无法统一处理。比如load事件不支持冒泡,所以即使开发者不使用event.stopPropagation,jQuery也必须防止它冒泡:jQuery.event={special:{load:{//防止触发image.load事件从冒泡到window.load//防止冒泡noBubble:true},focus:{//如果可能,触发原生事件,这样模糊/聚焦序列是正确的trigger:function(){},delegateType:"focusin"},}}8.external是Event,internal是数据缓存事件,两者不同externalEvent:$().on("click","#B",function(event){console.log("Awasclicked")})//click的事件是jQuery.EventjQuery.Event{handleObj{data:undefined,guid:2,handler:function(){console.log("A被点击")},命名空间:"clickA",origType:"click",选择器:"#B",类型:"click.clickA",},originalEvent:{//isMouseEvent},target:div#B,type:"click",delegateTarget:div#A,//fixflagjQuery331087940272164138:true,currentTarget:div#A,isDefaultPrevented:xxx,timeStamp:Date.now(),isDefaultPrevented:function(){returnfalse}}内部缓存events:letevents=dataPriv.get(this,"events")events[delegateCount:1,{data:undefined,guid:2,handler:function(){console.log("BdelegateAisclicked")},命名空间:“clickA”,origType:“click”,选择器:“#B”,类型:“click.clickA”,},{data:undefined,guid:1,handler:function(){console.log(“A被点击”)},命名空间:“”,origType:“点击”,选择器:未定义,类型:“click",}]九、为什么要用fix()重构js原生的MouseEvent对象?(1)jQuery有自己的一套事件处理机制,所以需要符合jQuery的事件对象(2)才可以通过data数据,即用户自定义数据十、触发机制$("#A").on("click",function(event){console.log(event,"Awasclicked")})element#A它本身绑定了一个click事件,但是click是一个native事件,通过绑定addEventListener来触发事件。但是!jQuery的trigger是$("#A").trigger("click")从trigger()的功能上可以解释jQuery为何将设计元素与数据分离:如果直接绑定,则无法通过触发机制触发点击事件,正是因为jQuery不直接将事件处理程序直接绑定到元素,而是采用单独处理,所以我们通过trigger触发点击事件和addEventListener触发的点击事件的处理流程是一致的,区别只是触发的方式不同。但是触发器触发的事件没有事件对象(event)、冒泡(bubble)这些特性,所以我们需要有一个函数来模拟事件对象,然后生成一个遍历树(eventPath)来模拟冒泡行为,这个就交给触发方法了关于$().trigger()的源码分析请看:jQuery源码分析之trigger()最后附上jQuery事件绑定触发整个流程的流程图过程:(完)