JavaScript基础知识——事件的基础知识

本博客分三部分来阐述事件:DOM事件流、事件处理程序、事件对象。

一、DOM事件流

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

(一)事件捕获阶段,document对象首先接收到事件,然后事件沿着DOM树一次往下,一直传播到事件的实际目标;

(二)处于目标阶段,即事件在实际目标上发生;

(三)事件冒泡阶段,事件从实际目标开始,沿着DOM树一级一级往上传播,直至document对象。

PS. 虽然“DOM2 级事件”规范明确要求捕获阶段不会涉及事件目标,但是多数支持DOM事件流的浏览器都实现了一种特定的行为:IE9、Safari、Chrome、Firefox 和Opera 9.5 及更高版本都会在捕获阶段触发事件对象上的事件。这样,就是有两个机会(事件捕获阶段和事件冒泡阶段)在目标对象上面操作事件。

二、事件处理程序

事件处理程序,共有三种,一是HTML事件处理程序,二是DOM0级事件处理程序,三是DOM2级事件处理程序。

(一)HTML事件处理程序:指在HTML标签中,使用一个与相应事件处理程序同名的HTML特性来指定的事件处理程序,如:
这种方式是不推荐的,因为导致了HTML与JS高度耦合。

(二)DOM0级事件处理程序:这是通过JavaScript指定事件处理程序的传统方式,即将一个函数赋值给一个事件处理程序属性。如:

var btn = document.getElementById("myBtn");
btn.onclick = function(){
    alert(this.id);//myBtn
};

删除通过DOM0级方法指定的事件处理程序,只要将事件处理程序属性的值设置为null即可。如:btn.onclick = null;
注意事项:DOM0级只能为一个元素添加一个事件处理程序。

(三)DOM2级事件处理程序:与DOM0级相比,DOM2级可以为一个元素添加多个事件处理程序。
DOM2级事件处理程序,定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener() 和 removeEventListener()。比如,在某个元素上为click事件添加/删除事件处理程序:

var btn = document.getElementById("myBtn");
var handler = function(){
    alert(this.id);
};
btn.addEventListener("click", handler, false);
//这里省略了其他代码
btn.removeEventListener("click", handler, false); //有效!

可以看到addEventListener() 和 removeEventListener() 都接收三个入参,第一个入参是事件名称,第二个参数是一个函数,第三个参数是一个boolean值。第三个参数是true时,表示在捕获阶段调用事件处理程序;第三个参数是false时,表示在冒泡阶段调用事件处理程序。
注意事项:
1)通过addEventListener() 添加的事件处理程序,只能通过调用 removeEventListener() 方法删除;
2)调用 removeEventListener() 方法删除某个事件处理程序时,参数必须和 addEventListener() 的参数完全一致,否则无法删除。所以,如果给第二个参数传入匿名函数,这个事件处理程序将无法删除。

三、事件对象

兼容 DOM 的浏览器会将一个 event 对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0 级或 DOM2 级),都会传入event 对象。event对象有几个属性和方法需要了解的:
(一)target、currentTarget属性
target属性,指向事件的实际目标;currentTarget指向事件处理程序所依附的目标。看下面的例子:

<!doctype html>
<html>  
    <head>
        <meta charset="utf-8">
        <script>
            window.onload = function(){
                var div = document.getElementById("A2");

                document.body.onclick = function(event){
                    console.log(event.target);
                    console.log("----------------");
                    console.log(event.currentTarget);
                } 
            }
        </script>
    </head>
    <body>
        <div id="A2" style="background:black;border: 1px solid blue;height: 200px;width: 400px;">
        </div>
    </body>
</html>

在点击ID为A2的div块后,打印结果如下图所示:
这里写图片描述

例子中,通过DOM0级的方式为body元素绑定了一个事件处理程序,所以console.log(event.currentTarget);语句会打印出body标签的内容。
另外,在事件处理程序内部,this 永远与 event.currentTarget 指向同一个对象。可以通过console.log(event.currentTarget === this);验证。

(二)preventDefault() 方法和 stopPropagation() 方法
preventDefault() 方法,用于阻止特定事件的默认行为,例如<a>标签的默认行为就是在被单击时会导航到其href 特性指定的URL。如果想阻止链接导航这一默认行为,那么通过链接的onclick 事件处理程序可以取消它。如下:

var link = document.getElementById("myLink");
link.onclick = function(event){
    event.preventDefault();
};

stopPropagation() 方法,用于立即停止事件在DOM 层次中的传播,即取消进一步的事件捕获或冒泡。看下面的例子:

<!doctype html>
<html>  
    <head>
        <meta charset="utf-8">
        <script>
            window.onload = function(){
                var div = document.getElementById("A2");
                div.onclick = function(event){
                    alert("div被点击了!");
                    event.stopPropagation();
                }
                document.body.onclick = function(event){
                    alert("Body Clicked!");
                } 
            }
        </script>
    </head>
    <body>
        <div id="A2" style="background:black;border: 1px solid blue;height: 200px;width: 400px;">
        </div>
    </body>
</html>

上面的代码中,如果点击div块,只会弹出一个警告框,显示信息”div被点击了!”。而如果把event.stopPropagation();这一行代码删除,则会弹出两个警告框。
需要注意的是,当event的bubbles属性为true时,stopPropagation()方法才会起作用。

四、喜欢搞事情的IE浏览器

IE内核的浏览器在国内的用户还是蛮多的,所以我们还是要了解下搞事情的IE浏览器到底搞了些什么事情。
(一)IE浏览器在事件处理程序搞的事情
IE 浏览器实现了与DOM 中类似的两个方法:attachEvent() 和 detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。注意:通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
    alert("Clicked");
});

使用 attachEvent() 添加的事件可以通过 detachEvent() 来移除,条件是必须提供相同的参数。与DOM 方法一样,这也意味着添加的匿名函数将不能被移除,如上面例子中的事件处理程序无法通过 detachEvent() 移除。需要写成下面的形式,才可正常地移除事件处理程序:

var btn = document.getElementById("myBtn");
var handler = function(){
    alert("Clicked");
}
btn.attachEvent("onclick", handler);
//省略其他代码
btn.detachEvent("onclick", handler);

(二)IE浏览器在事件对象上搞的事情
IE浏览器在事件对象上搞的事情,主要有两个方面,一个是访问event对象的方式,另一个是event对象的属性。

IE浏览器中,访问event对象的方式,取决于指定事件处理程序的方法。
(1)在使用DOM0 级方法添加事件处理程序时,需要通过window.event来访问event对象;
(2)在使用attachEvent()添加事件处理程序时,可以直接访问event对象;
(3)通过HTML特性指定的事件处理程序时,可以直接通过event变量访问event对象。

IE浏览器中的event对象的属性也和其他兼容DOM的浏览器的event对象的属性不同。如下:
(1)srcElement属性:同DOM中的target属性;温馨提示:在IE浏览器中,最好使用srcElement属性来指定当前目标,而不要使用this。
(2)returnValue属性:值为boolean型,默认为true,当设置为false时,会取消事件的默认行为,与DOM中的 preventDefault() 方法的作用相同;
(3)cancelBubble属性:值为boolean型,默认为false,当设置为true时,会取消事件冒泡,与DOM中的 stopPropagation() 方法的作用相同。

五、跨浏览器的事件处理

这里分享一个跨浏览器的事件处理程序,代码如下:

var EventUtil = {
    addHandler: function(element, type, handler){
        if (element.addEventListener){
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent){
            element.attachEvent("on" + type, handler);
        } else {
            element["on" + type] = handler;
        }
    },
    removeHandler: function(element, type, handler){
        if (element.removeEventListener){
            element.removeEventListener(type, handler, false);
        } else if (element.detachEvent){
            element.detachEvent("on" + type, handler);
        } else {
            element["on" + type] = null;
        }
    },
    getEvent: function(event){
        return event ? event : window.event;
    },
    getTarget:function(event){
        return event.target || event.srcElement;
    },
    preventDefault: function(event){
        if (event.preventDefault){
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    stopPropagation: function(event){
        if (event.stopPropagation){
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值