JS事件知识点总结

来源:互联网 发布:洗菜盆 知乎 编辑:程序博客网 时间:2024/05/21 07:27

13 事件

JavaScript与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码。

13.1 事件流

事件流描述的是从页面中接受事件的顺序。IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕获流。后在W3C组织下,JS支持了冒泡流和捕获流,考虑到IE低版本浏览器仍只支持的冒泡流,为了兼容更多版本浏览器,建议使用冒泡流。

13.1.1 事件冒泡

IE的事件流叫事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接受,然后逐级向上传播到较为不具体的节点(文档)。

13.1.2 事件捕获

事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。

13.1.3 DOM事件流

“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。

首先发生的事件捕获,为截获事件提供了机会。然后是实际的目标接受到事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件作出响应。

虽然该规范明确要求捕获阶段不会涉及事件目标,但是部分浏览器都会在捕获阶段触发事件对象上的事件。

13.2 事件处理程序

事件就是用户或浏览器自身执行的某种动作。而响应某个事件的函数就叫做事件处理程序(或事件侦听器)。事件处理程序的名字以“on”开头,因此click事件的时间处理程序就是onclick等等。

13.2.1 HTML时间处理程序

某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTML特性来指定。这个特性的值应该是能够执行的JavaScript代码。

换句话说,就是直接在HTML中写onclick=“ “事件。例如:

<input type="button" value="Click Me" onclick="alert('Clicked‘)"/>

事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。

在HTML中定义的事件处理程序可以包含要执行的具体动作,也可以调用在页面其他地方定义的脚本,如下面的例子所示:

<script type="text/javascript">    function showMessage(){        alert("Hello world");    }</script><input type="button" value="Click Me" onclick=“showMessage()"/>

在HTML中指定时间处理程序有两个缺点。首先,存在一个时差问题。因为用户可能会在HTML元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。另一个缺点就是,这样扩展事件处理程序的作用域链在不同浏览器中会导致不同结果。不同JavaScript引擎遵循的标识符解析规则略有差异,很可能会在访问非限定对象成员时出错。通过HTML指定事件处理程序的最后一个缺点是HTML与JavaScript代码紧密耦合。如果要更换事件处理程序,就要改动两个地方:HTML代码和JavaScript代码。

13.2.2 DOM0级事件处理程序

即为指定对象添加事件处理,如下示例:

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

在这些代码运行以前不会指定事件处理程序,因此如果这些代码在页面中位于按钮后面,就有可能在一段时间内怎么单机都没有反应。

使用DOM0级放大指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行;换句话说,程序中的this引用当前元素。如下:

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

在事件处理程序中通过this访问元素的任何属性和方法。也可以删除通过DOM0级方法指定的事件处理程序,如下:

btn.onclick = null; //删除事件处理程序

13.2.3 DOM2级时间处理程序

“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。

所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。

要在按钮上为click事件添加事件处理程序,可以使用下列代码:

var btn = document.getElementById("myBtn");btn.addEventListener("click",function(){    alert(this.id);},false);

与DOM0方法一样,这里添加的事件处理程序也是在其依附的元素的作用域中运行。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。即直接在上述例子下面继续添加代码:

btn.addEventListener("click",function(){    alert("Hello world");},false);

==两个事件处理程序会按照添加它们的顺序触发==

通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。这也意味着通过addEventListener()添加的匿名函数将无法移除,如下示例:

btn.removeEventListener("click",function(){ //没有用!    alert(this.id);},false);

大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。

13.2.4 IE事件处理程序

IE实现了DOM中类似的两个方法:attachEvent()()和detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。该事件处理程序会被添加到冒泡阶段。

要使用attachEvent()为按钮添加一个事件处理程序,可以使用以下代码。

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

==需注意的是,这里第一个参数是“onclick”,而非DDM中的“click”。==

==在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。==

IE事件处理程序会在全局作用域中运行,因此this等于window。如下示例:

var btn = document.getElementById("myBtn");btn.attachEvent("onclick",function(){    alert(this === window);     //true});

与DOM2级时间处理程序的添加方法类似,该添加方法也可以为一个元素添加多个事件处理程序。但是两个事件以相反的顺序被触发。

该方法添加的事件可以通过detachEvent()来移除,条件是必须提供相同的参数。与DOM方法一样,这也意味着添加的匿名函数将不能被移除。

13.2.5 跨浏览器的事件处理程序

要保证处理事件的代码能在大多数浏览器下一致地运行,只需关注冒泡阶段。

第一个要创建的方法是addHandler(),它的职责是视情况分别使用DOMO级方法、DOM2级方法或IE方法来添加事件。这个方法属于一个名叫EventUtil的对象,本书将使用这个对象来处理浏览器间的差异。addHandler()方法接受3个参数:要操作的元素、事件名称和事件处理程序函数。

与addHandler()对应的方法是removeHandler(),它也接受相同的参数。

EventUtil的用法如下所示:

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;        }    }};
原创粉丝点击