Web前端之路前端开发

JavaScript学习笔记(2)DOM 事件流&&am

2017-02-13  本文已影响130人  机智的马里奥

定义:

1.事件流

事件流分成两种:事件冒泡和事件捕获:

DOM事件流

“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。首先发生的是事件捕获阶段,为截获事件提供了机会。然后是实际的目标接收事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件作出相应。

图片来源于网络

以上图为例,单击div会按照图上显示的顺序触发事件。

浏览器支持

例子

addEventListener

在写例子之前,先简单介绍一个方法:addEventListener

比较事件冒泡和事件捕获

接下来就用addEventListener来展示事件冒泡和事件捕获的区别:
先放上html 和 css 代码:

<div id="level1">
    <div id="level2">
        <div id="level3"></div>
    </div>
</div>
#level1{
    background:red;
    height:200px;
    width:200px;
}
    
#level2{
    background:orange;
    height:100px;
    width:100px;
}
    
#level3{
    background:yellow;
    height:50px;
    width:50px;
}

呈现的效果很简单,就是三个不同颜色的div块:


事件流对比.png

然后用JS给每一个div注册一个点击事件,为了更加直观,当每一个div的点击事件被触发时,会显示一条该div块背景颜色的消息,这样我们就能清楚地看到各个div的click事件被触发的先后顺序

var level1=document.getElementById('level1');
var level2=document.getElementById('level2');
var level3=document.getElementById('level3');

level.addEventListener('click',function(){
    alert('yellow');
},false);

leve2.addEventListener('click',function(){
    alert('orange');
},false);

leve3.addEventListener('click',function(){
    alert('red');
},false);

根据上面的例子,addEventListener的布尔值参数被设置为false,所以会在冒泡阶段调用事件处理程序。当点击黄色方块后,会先后弹出消息"yellow","orange","red";点击橙色方块后,会弹出消息"orange","red";点击红色方块后,会弹出"red".这个结果也印证了我们之前所说的事件冒泡会使事件开始时由最具体的元素接受,然后逐级向上传播到较为不具体的节点。这里的黄色方块是嵌套在最里面的div块,所以是该例子中最具体的节点,红色块是最外层的div快,在该例中是最不具体的节点。

接着我们再测试一下用事件捕获的思想会获得什么结果:
html和css代码都不需要变动,只需要对JS代码稍作修改:把布尔值从false改成true.

var level1=document.getElementById('level1');
var level2=document.getElementById('level2');
var level3=document.getElementById('level3');

level.addEventListener('click',function(){
    alert('yellow');
},true);

leve2.addEventListener('click',function(){
    alert('orange');
},true);

leve3.addEventListener('click',function(){
    alert('red');
},true);

结果还是和我们预想的一样,当点击黄色方块后,会先后弹出消息"red","orange","yellow";当点击橙色方块后,会先后弹出消息"red","orange";点击红色方块时仍然只有"red".结果和上例恰好相反。

从上述两个例子,我们可以清晰地看出事件冒泡和事件捕获两种事件流的区别。

事件处理程序

4种为事件指定处理程序的方式:
    <input type="button" value="click" onclick="showMsg()"/>
    function showMsg(){
        alert("hello world");
    }
    btn.onclick=function(){
        alert("hello world");
    };
    btn.addEventListener("click",function(){},false); //事件冒泡
    btn.addEventListener("click",function(){},true); //事件捕获
    btn.attachEvent("onclick",function(){
        alert("hello world");
    });

事件代理(event delegation)

定义

事件代理允许我们需要为很多元素添加事件的时候,可以将事件添加到它们的父节点而将事件委托给父节点来触发处理函数,这得益于事件冒泡机制。

举例

html 代码如下:

<ul id="parent">
  <li id="child1">item1</li>
  <li id="child2">item2</li>
  <li id="child3">item3</li>
  <li id="child4">item4</li>
  <li id="child5">item5</li>
</ul>

Javascript代码如下:

var parent=document.getElementById("parent");
parent.addEventListener("click",function(event){
    if(event.target&&event.target.nodeName=="LI"){
    alert("list item "+event.target.id+" was clicked");
  }
});

这里我们假设需要为每一个Li节点添加一个点击事件,如果依次添加,尤其是如果你需要在程序内不同的地方添加和删除点击事件,那么就会非常麻烦。其中一个解决方法便是将点击事件添加到LI节点的父元素UL节点上,如上述代码所示,当事件冒泡到父节点以后,通过target属性可以得知哪一个LI节点被点击了,从而进行相应的处理。此例只是将获取的LI元素的ID显示出来了。

jQuery中的delegate()

delegate()方法为指定的元素(被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数,该方法有四个参数,分别是选择器,事件类型,传递到函数的数据,函数,传递到函数的数据可以选填。

举例

还是上面那个例子,html代码不变,jQuery代码如下:

    $("#parent").delegate("li","click",function(){
        $(this).after("clicked");
    })

为什么要用事件代理?

事件代理只需要在父元素绑定一次所需事件,而不需要在子元素上绑定多次,从而大大提升了性能,也提升了编码效率。

参考

上一篇下一篇

猜你喜欢

热点阅读