JS学习笔记——事件

1.事件流

当我们点击网页上的某一个元素时,触发的动作不仅仅跟这个元素有关,还跟包含这个元素的所有上层容器有关。触发事件流的流动有一个先后顺序,目前有两种:1.IE所提出的事件冒泡;2.Netscape所提出的事件捕获。
DOM事件流则是综合了前面两种事件流,先捕获再冒泡。现代浏览器大多支持DOM事件流。



2.事件处理程序

为元素绑定相应的事件处理程序有3种方法:HTML、DOM0级、DOM2级。事件处理程序以”on”开头,如”click”事件的处理程序是”onclick()”。

2.1 HTML事件处理

我们把事件处理程序当做html的元素属性加入html标签中。这种方法的最大缺点就是html和js紧耦合。

<input type="button" value="button" onclick="alert(`Click Me`)" />
<input type="button" value="button" onclick="test()" />

<script>
function test() {
    //...
}
</script>

2.2 DOM0级事件处理

通过DOM操作获取元素,元素都带有事件处理(比如onclik())的属性,我们把函数赋值给该属性即可。在事件处理程序中,this指向给调用该事件处理程序的元素(在事件委托中,this就指向那个尽量高层次的元素)。若想删除事件处理程序,将该属性赋值null即可。DOM0级绑定的事件处理程序会发生在冒泡阶段。

var p = document.getElementById('p');
p.onclick = function() {
    alert(this.id);//p
}
p.onclick = null;//删除绑定的事件处理程序

2.3 DOM2级事件处理

DOM2级事件处理程序的功能比DOM0级更加丰富。DOM2级可以一个事件添加多个处理程序,还可以指定程序在冒泡阶段调用还是捕获阶段调用。DOM2级要删除处理程序,需要传入添加函数时的那个函数参数,这就说明,添加的匿名函数无法删除。

var p = document.getElementById('p');
p.addEventListener("click", function(){
    alert(this.id);//p
}, false);//第三个参数 true:捕获阶段调用;false:冒泡阶段调用;

//该移除函数没有起作用
p.removeEventListener("click", function(){
    alert(this.id);
}, false);

2.4 IE事件处理

虽然IE9也支持DOM2级事件处理程序(DOM事件流),但在IE9以前,是只支持IE事件处理(IE事件流)的。IE事件流是事件冒泡。IE事件处理程序与DOM2级事件处理程序非常相似。IE事件处理只支持两个参数,第三个参数无法选择捕获还是冒泡。在IE8以及更早版本中,只支持冒泡。与DOM2级不同的是,这里的this指向全局window。
这里我们注意,并不是所有IE浏览器都是IE事件处理(IE事件流),像IE9就支持DOM事件流,支持DOM事件流,也支持DOM2级事件处理程序。

var p = document.getElementById('p');

p.attachEvent("onclick", function(){//注意这里是"onclick",而不是DOM2级的"click"
    alert(this === window);//true
});

//与DOM2级一样,匿名函数无法被删除
p.detachEvent("onclick", function(){
    alert(this === window);//true
});

3.DOM事件对象

事件对象分为DOM事件对象和IE事件对象,IE就是个奇葩的存在,除了IE之外,其他浏览器都是DOM事件对象。
事件处理程序会接收一个事件对象,该事件对象中有许多跟事件有关的属性,比如type、churentTarget、target等。
下面我们区分一下三个容易混淆的属性thistargetcurrentTarget。this始终等于currentTarget,这两个又等于调用处理程序的元素。target等于动作真实发生的对象。

<body>
    <div id='div'>
        <p id='p'>hello!</p>
    </div>
</body>

//div是p的父元素,如果点击p,event.target就是p
//如果点击div其他地方(不是p),event.target就是div
div.detachEvent("onclick", function(event){
    //event.type == "click"
    alert(this === div);//true
    alert(event.currentTarget === div);//true
    alert(event.target === p);//true
});

4.事件代理(事件委托)

如果我们有许多的元素需要绑定事件处理程序,按照上面的方法:先使用DOM获取元素,再给元素绑定函数。这种方法会使得web性能下降:DOM操作耗时;函数的本质是对象,耗内存。
这种场景的解决方法就是使用事件代理,即利用事件冒泡,给尽量高层次的元素绑定一个事件,在这个事件中,根据事件对象的属性来做相应的处理。

div.onclick = function(event) {
    switch(event.target.id) {
        case 'p':
            alert('p');
            break;
        case 'div':
            alert('div');
            break;
    }
}
posted @ 2017-04-24 22:25  水煮海鲜  阅读(125)  评论(0编辑  收藏  举报