1.事件流
- 要理解DOM相关事件,要先理解事件流这个概念,事件流描述的是从页面接受事件的顺序。
- 为什么会产生事件流?
-
我们可以想到一个问题:当我们在浏览器上对着一个元素点击时,你点击的不仅仅是这个 元素本身;
-
这是因为我们的HTML元素是存在父子元素叠加层级的;
-
比如一个span元素是放在div元素上的,div元素是放在body元素上的,body元素是放在html元素上的;
-
<div class="box">
<span class="word"></span>
</div>
.box{
display: flex;
justify-content: center;
align-items: center;
width: 200px;
height: 200px;
background-color:red;
}
.word{
width: 100px;
height: 100px;
background-color:green;
}
// 1.获取元素
var divEl=document.querySelector(".box")
var spanEl=document.querySelector(".word")
var bodyEl=document.body
// 2.添加监听(事件冒泡)
divEl.addEventListener("click",function(){
console.log("div被点击了")
})
spanEl.addEventListener("click",function(){
console.log("span被点击了")
})
bodyEl.addEventListener("click",function(){
console.log("body被点击了")
})
// 2.添加监听(事件捕获)
divEl.addEventListener("click",function(){
console.log("div被点击了")
},true)
spanEl.addEventListener("click",function(){
console.log("span被点击了")
},true)
bodyEl.addEventListener("click",function(){
console.log("body被点击了")
},true)
- 事件冒泡:默认情况下事件是从最内层的span向外依次传递的顺序(span -> body),这个顺序我们称之为事件冒泡(Event Bubble)
- 事件捕获:另外一种监听事件流的方式就是从外层到内层(body -> span),这种称之为事件捕获(Event Capture)
2.事件委托
- 事件委托,通俗说就是将元素的事件委托给它的父级或更外级的元素处理,它的实现机制就是事件冒泡。
- 因为当子元素被点击时,父元素可以通过冒泡可以监听到子元素的点击;
- 并且可以通过event.target获取到当前监听的元素;
- 案例:一个ul中存放多个li,点击某一个li会变成红色。
- 方案一:监听每一个li的点击,并且做出相应;
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
.active {
color: red;
font-size: 20px;
}
// 1.每一个li都监听自己的点击, 并且有自己的处理函数(自己的函数)
var liEls = document.querySelectorAll("li")
for (var liEl of liEls) {
// 监听点击
liEl.onclick = function(event) {
event.currentTarget.classList.add("active")
}
}
存在问题:
1.给每一个列表都绑定事件,消耗内存
2.当有动态添加的元素时,需要重新给元素绑定事件
- 方案二:在ul中监听点击,并且通过event.target拿到对应的li进行处理;
// 1.每一个li都监听自己的点击, 并且有自己的处理函数(自己的函数)
var liEls = document.querySelectorAll("li")
for (var liEl of liEls) {
// 监听点击
liEl.onclick = function(event) {
event.currentTarget.classList.add("active")
}
}
事件委托的优点:
1.只需要将同类元素事件委托给父级或者更外级的元素,不需要给所有元素都绑定事件,减少内存占用空间,提升性能。
2.动态新增的元素无需重新绑定事件