事件的捕获和事件的冒泡
作用
其实他们的作用都是一样的:决定我们事件执行的先后顺序。只不过这两种规则完全是一个逆过程。
介绍
- 事件的捕获由网景公司提出,他指出事件执行的顺序应该是由外到内的过程:document->html->body->dom
- 事件的的冒泡由微软公司提出,他指出事件的执行顺序应该是由内到外冒泡的过程:dom->body->html->document
两种方式吵得不可开交,最终,w3c采取了一种折中的方式:事件触发的顺序:先捕获后冒泡。这也符合我们的认知习惯,从外到内,再从内到外。但是事件只能选择在捕获阶段触发,还是在冒泡阶段触发。
事件默认情况下,是在冒泡过程中触发的。
addEventListener()方法的第三个参数就是一个bool值,决定我监听的事件是在捕获阶段触发true,还是在冒泡阶段触发false 默认值为true
小思考:
当一个元素绑定了若干个事件那么他的执行顺序是怎样的呢?比如div1绑定了两个click事件,一个是在冒泡过程执行。一个是在捕获阶段执行。那么哪个先执行呢?分两种情况
-
div1不是目标元素,而是路过的元素。
相对简单一点,在捕获阶段执行捕获阶段的click事件,然后再在冒泡过程执行冒泡阶段的click事件。 -
div1是目标元素。
这时候就是谁先绑定谁先执行。
tips:几乎所有事件都有冒泡过程,但是focus没有。
如何阻止事件的冒泡
event.stopPropagation()
eaxmple:
代码:
<div class="aaa">
</div>
</div>
<script>
document.getElementsByTagName("div")[0].addEventListener("click",function(){console.log(1);});
document.getElementsByTagName("div")[1].addEventListener("click",function(event){console.log(2);event.stopPropagation();});
</script>
直接在子代div的click事件里面阻止冒泡即可,他就不会继续传播点击事件。
事件委托机制
事件委托的原理
其实就是利用事件冒泡机制,事件可以逐级向上传播的特点,从而实现把事件委托给上级元素来处理。
为什么要进行事件委托
- 拿ul和li来举例,如果我需要实现一个点击li标签从而打印li标签的内容的需求,那么我得给每一个li标签都绑定一个click事件,从而来实现需求,但是如果我们的li元素特别的多,那么我们的js代码就会显得特别的臃肿且重复,储存起来也耗费内存,并且给这么多元素绑定事件,那么会导致页面性能下降。我们完全可以把这个click事件委托给ul来实现。这样我们只需要定义一个click事件就可以达到目的。
事件委托的实现关键
我个人觉得是这个event.target对象,他代表你当前点击的这个DOM元素,ie中这个对象应该是event.srcElement
example
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.getElementsByTagName("ul")[0];
ul.addEventListener("click",function(e){
var e = e.target||e.srcElement;//兼容性
if(e.nodeName.toLowerCase()=="li")//排除没有点到li标签的情况
{
console.log(e.innerHTML);
}
})
</script>
小思考
如果li元素并不是一个简单的li元素,他还有很多子元素那么这时候该怎么处理呢? 写个循环就可以解决了。
<script>
var ul = document.getElementsByTagName("ul")[0];
ul.addEventListener("click",function(e){
var e = e.target||e.srcElement;//兼容性
while(e.nodeName.toLowerCase()!="ul")
{
if(e.nodeName.toLowerCase()=="li")
{
console.log(e.innerHTML);
break;
}
else
{
e=e.parentNode;
}
}
})
</script>