模拟实现jQuery的$().on()和$().trigger()
前言:
仅仅是简单模拟了$().on()和$().trigger()
,仅支持id选择器,事件冒泡与事件委托。
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模拟jQuery的事件绑定到触发过程</title> </head> <body> <div id="A" style="background-color: deeppink"> 这是A <div id="B" style="background-color: aqua"> 这是B </div> </div> <script> //数据缓存 let events={} function $(elemId){ //只考虑理想情况 const element=document.querySelector(elemId) // console.log(element,'element27') function returnTrue(){ return true } function returnFalse(){ return false } $.event={ //不考虑用户的自定义事件 add:function (elemId,type,selectorReal,callbackReal) { let elemData=events[elemId] if(!elemData){ events[elemId]=elemData={} } elemData.handle=function(nativeEvent){ //锁定this return $.event.dispatch.call(this,nativeEvent) } if(!elemData[type]){ elemData[type]=[] elemData[type].delegateCount=0 //addEventListener只绑定一次 document.querySelector(elemId).addEventListener(type,elemData.handle) } let handlersCount=elemData[type].length let handlerObj={ type:type, handler:callbackReal, guid:++handlersCount, selector:selectorReal, } if ( selectorReal ) { //在下标为handlers.delegateCount++的位置插入委托事件 elemData[type].splice( elemData[type].delegateCount++, 0, handlerObj); } else { elemData[type].push(handlerObj) } }, dispatch:function (nativeEvent,) { let event=$.event.fix(nativeEvent) let handlers=events['#'+this.id][event.type] //继续锁定this let handlerQueue=$.event.handlers.call(this, event, handlers ) //为什么要用变量代替,因为循环的时候,需要保留该值 let matched,handleObj let i=0 while((matched=handlerQueue[i++])&&!event.isPropagationStopped()){ let j=0 while((handleObj=matched.handlers[j++])){ event.handleObj=handleObj handleObj.handler(event) } } // return event }, fix:function (nativeEvent,) { let $event={} //就是MouseEvent $event.originalEvent=nativeEvent $event.target=nativeEvent.target $event.type=nativeEvent.type // delegateTarget: div#A, // currentTarget: div#A, $event.timeStamp=Date.now() $event.stopPropagation=function() { this.isPropagationStopped = returnTrue; nativeEvent.stopPropagation() } $event.isPropagationStopped=returnFalse //fix 的标志 $event['chen'+(new Date()).valueOf()]=true return $event }, handlers:function (event,handlers) { let delegateCount = handlers.delegateCount let cur=event.target let handlerQueue=[] for(;cur!==this;cur=cur.parentNode||this){ let matchedHandlers = [] for(let i=0;i<delegateCount;i++){ let handleObj=handlers[i] matchedHandlers.push( handleObj ) handlerQueue.push( { elem: cur, handlers: matchedHandlers } ) } } cur=this if ( delegateCount < handlers.length ) { handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ) } return handlerQueue }, trigger:function (elemId,type) { let element=document.querySelector(elemId) let eventPath=[] let cur=element let event={} event.target=cur event.type=type for(;cur;cur=cur.parentNode){ eventPath.push( cur ); } let i=0 //不考虑阻止冒泡的情况 while((cur=eventPath[i++])){ let handle=events['#'+cur.id]&&events['#'+cur.id].handle if(handle){ handle.call(cur,event) } } }, } return { on:function (type,selector,callback) { let callbackReal,selectorReal if(!type){ return } //如果selector是funcion的话,就没有委托元素了 if(typeof selector==='function'&&!callback){ selectorReal=undefined callbackReal=selector }else if(typeof selector==='string'&&callback){ selectorReal=selector callbackReal=callback } return $.event.add(elemId,type,selectorReal,callbackReal) }, trigger:function (type) { return $.event.trigger(elemId,type) }, } } //仅支持id选择器,事件冒泡与事件委托 //=========test1=============== $("#A").on("click" ,function (event) { console.log(event,"A被点击了") }) $("#A").on("click" ,function (event) { console.log(event,"A又被点击了") }) //=========test2=============== // $("#A").on("click" ,function (event) { // console.log(event,"A被点击了") // }) // $("#A").on("click" ,"#B",function (event) { // event.stopPropagation() // console.log(event,"B委托A被点击了") // }) //=========test3=============== // $("#A").on("click" ,function (event) { // console.log(event,"A被点击了") // }) // $("#B").on("click",function (event) { // // event.stopPropagation() // console.log(event,"B被点击了") // }) //==========test4============== // $("#A").on("click" ,function (event) { // console.log(event,"A被点击了") // }) // $("#A").on("click" ,function (event) { // console.log(event,"A又被点击了") // }) // $("#A").trigger("click") </script> </body> </html>
根据上篇的流程图写出即可。
思路请看:
(完)