前言:
仅仅是简单模拟了$().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>

根据上篇的流程图写出即可。

思路请看:


(完)