前言:
仅仅是简单模拟了$().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>
根据上篇的流程图写出即可。
思路请看:
(完)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。