JavaScript与HTML之间的交互是通过事件实现的。在学习事件委托之前,我们需要先了解事件含义、事件绑定、事件监听、事件派发。
什么是事件?
简单来讲,可以理解为有一群人关注了一事件,如果该事件有变化,就会通知到这群人。
事件有3个特点:
1、订阅/监听了xxx事件
2、xxx发生变化
3、订阅人得到通知
站在前端开发的角度来想事件,就是“代码监听了用户,当用户操作发生变化,代码得到通知”
如何监听事件?
1、DOM level 0 在JS代码里添加:事件: button.onclick = function(){}
例:
<button id=xx>click me</button>
<script>
xx.onclick = function (e){
console.log('hi')
console.log(this)
console.log(e)
}
2、DOM level 2 事件: button.addEventListener('click', function(){})
例:
function event1(){
console.log('给ul绑定成功1')
}
//给相应的事件添加监听器
var ul =document.querySelector('#list')
ul.addEventListener('click',event1)
事件机制:冒泡&捕获
<div class="parent">
<div class="child"></div>
</div>
如果parent和child同时被监听,对于捕获阶段的通知机制,先出发parent监听,然后是child;冒泡则反之。在addEventListener()里添加一个参数false(执行冒泡)或者true(执行捕获),addEventListener()默认为false
事件委托
先看下面的例子:
<ul id="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
var list = document.querySelector('list')
list.addEventListener('click',function (e){
if(e.target.tagName === 'LI'){
console.log('当前元素事件触发成功')
}
})
这是常规的实现事件委托的方法,但是这种方法有漏洞,当监听的元素里存在子元素时,那么我们点击这个子元素事件会失效,所以我们可以联系文章上一小节说到的冒泡事件传播机制来解决这个bug。改进的事件委托代码:
var ul = document.querySelector('list')
list.addEventListener('click',function (e){
var l = e.target
//从target(点击)元素向上找currentTarget(监听)元素,找到了想委托的元素就触发事件,如果直到找到监听li的包含元素块依然没找到依然没有找到,就返回null
while(l.tagName !== 'LI'){
l = l.parentNode
if(l === ul){
l = null
break;
}
}
if (l) {
console.log('你点击了ul里的li')
}
})
事件委托可以减少监听器,减少内存。