シミュレーションはjQueryの$()を実現する.on()と$().trigger()
5744 ワード
前言:
コード:
前編のフローチャートに基づいて書けばいいです.
考え方を見てください.
(完)
$().on() $().trigger()
を単純にシミュレートしただけで、idセレクタのみをサポートし、イベントバブルとイベント依頼をサポートします.コード:
jQuery
A
B
//
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")
前編のフローチャートに基づいて書けばいいです.
考え方を見てください.
(完)