
导读
-
DOM事件绑定的几种方式
- DOM元素上面绑定
- js代码匿名绑定
- IE事件监听绑定:attachEvent / detachEvent
- 事件监听绑定:addEventListener / removeEventListener
- 兼容IE的事件监听
-
事件流
- 事件流分为哪几个阶段?
- DOM事件流的发展
-
事件委托
- 什么是事件委托
- 事件委托的好处
- jquery中的事件委托
- 如何实现事件委托
-
target 与 currentTarget的区别是什么?

🐑 DOM事件绑定的几种方式
1.DOM元素上面绑定
<button onclick="btnClick1()" onclick="btnClick2()">click me</button>
<script>
function btnClick1(){console.log('click!1')}
function btnClick2(){console.log('click!2')}
</script>
如果绑定了同一元素绑定了多个onclick 事件,那么只会执行第一个。
2.js代码匿名绑定
btn.onclick = function(){console.log('1')}
btn.onclick = function(){console.log('2')}
如果是在js里面匿名绑定的,那么只会执行最后一个。
3.IE事件监听绑定:attachEvent / detachEvent
btn.attachEvent('onclick', function(){})
1.事件名,带有on
2.如果同一元素绑定了多个click 事件,都会执行,并且有先后顺序。
3.注意:这个方法,chrome不支持,只有IE支持
4.绑定了事件记得取消绑定,避免内存泄漏
4.事件监听绑定:addEventListener / removeEventListener
btn.addEventListener('click',function(){}, false) // 可以区分捕获阶段 和 冒泡阶段
1.事件名不带on
2.如果绑定了同一元素绑定了多个click 事件,都会执行,并且有先后顺序。
3.并且第三个参数的意思是是否开启/使用事件捕获阶段,默认是false,就是默认是冒泡阶段。
4.绑定了事件记得取消绑定,避免内存泄漏
5.兼容IE的事件监听
if (a.addEventListener) {
a.addEventListener('click', function(){
console.log('is addEventListener!')
})
} else if (a.attachEvent) {
a.attachEvent('onclick', function(){
console.log('is attachEvent!')
})
} else {
console.log('others')
}
🐑 事件流?
事件流分为哪几个阶段?

1.捕获阶段:从上往下,document会先捕获到,到html,body,...,直到触发事件的那个元素
2.目标阶段:触发事件的那个元素
3.冒泡阶段:从下往上,触发事件的那个元素往父元素,...,到body,html,document
DOM事件流的发展
其实刚开始DOM0的时候是只有目标阶段 和 冒泡阶段的,直到出现了DOM2,才引进了捕获阶段。
1.DOM0
DOM0事件流只有两个阶段:目标阶段 + 冒泡阶段
btn.onclick = function(){
}
2.DOM2(IE不支持)
DOM2事件流只有3个阶段:捕获阶段 + 目标阶段 + 冒泡阶段
那么DOM2里面如何区分捕获阶段和冒泡阶段?
addEventListener 第二个参数的意思是,是否开启事件捕获。可以区分,true 事件捕获,默认是false 事件冒泡。
btn.addEventListener('click',function(){
}, true) // true 事件捕获
btn.removeEvenetListener('click',function(){
}, false) // false 事件冒泡(默认)
🐑事件委托
什么是事件委托
事件委托是,把自己元素的响应事件委托到其他元素上面。一般是委托再父元素上。
事件委托的好处
1.减少内存的消耗
如果是一个列表,我们给每个列表项都绑定同样的事件,是非常消耗内存的。
我们可以绑定到父组件列表上面,这样可以减少内存的消耗;
2.减少重复工作
我们的列表项,如果删除增加,都要重复进行一个操作就是删除事件和绑定事件。
如果我们绑定在父组件上面,我们就可以不用做这些重复的工作了。
jquery中的事件委托
on/delegate
如何实现事件委托
事件委托一般是由 事件冒泡来实现的
案例🌰:使用addEventListener点击li弹出内容,并且动态添加li之后有效
<ul id="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
// 给父层元素绑定事件
document.getElementById('list').addEventListener('click', function (e) {
var target = event.target
if (target.nodeName.toLocaleLowerCase === 'li') {
console.log('the content is: ', target.innerHTML);
}
});
🐑 target 与 currentTarget的区别是什么?
target指的是目标阶段。
currentTarget指的是捕获阶段,目标阶段 和 冒泡阶段。(一般指目标元素的父级)
<div id="c">c
<div id="b">b
<div id="a">a</div>
</div>
</div>
const b = document.getElementById('b');
const a = document.getElementById('a');
const c = document.getElementById('c');
b.addEventListener('click', (e)=>{
console.log("click b=>", "target:",e.target, "currentTarget:",e.currentTarget)
})
//b.addEventListener('click', (e)=>{
// console.log("click b=>", "target:",e.target, "currentTarget:",e.currentTarget)
//},true) //捕获阶段
a.addEventListener('click',(e)=>{
console.log("click a=>", "target:",e.target, "currentTarget:",e.currentTarget)
})
//a.addEventListener('click',(e)=>{
// console.log("click a=>", "target:",e.target, "currentTarget:",e.currentTarget)
//},true) //捕获阶段
c.addEventListener('click',(e)=>{
console.log("click c=>", "target:",e.target, "currentTarget:",e.currentTarget)
})
//c.addEventListener('click',(e)=>{
// console.log("click c=>", "target:",e.target, "currentTarget:",e.currentTarget)
//},true)//捕获阶段

1.当点击c模块的时候
捕获阶段:c(currentTarget)
目标阶段:c (target)
冒泡阶段:c(currentTarget)

2.当点击b模块的时候
捕获阶段:c
经过c模块,触发了c模块的click事件,所以c模块的currentTarget是c模块,但是target还是b模块
目标阶段:b
对于b模块自己来说,target 和 currentTarget都是自己
冒泡阶段:c
经过c模块,触发了c模块的click事件,所以c模块的currentTarget是c模块,但是target还是b模块
点击b模块.jpg

3.当点击a模块的时候
捕获阶段:c -- b
经过了c模块和b模块,所以触发了c,b模块的点击事件。对于c模块来说,currentTarget就是c模块,target还是a模块。对于b模块来说,currentTarget就是b模块,target还是a模块。
目标阶段:a
对于a模块自己来说,target 和 currentTarget都是自己
冒泡阶段:b --- c
经过了c模块和b模块,所以触发了c,b模块的点击事件。对于c模块来说,currentTarget就是c模块,target还是a模块。对于b模块来说,currentTarget就是b模块,target还是a模块。

最后
