29-JavaScript高级程序设计-事件流&事件处理程序

本文介绍了事件流的概念,包括事件冒泡与事件捕获两种模型,并详细对比了HTML事件处理程序、DOM0级/DOM2级事件处理程序以及IE事件处理程序的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、事件

1. 事件流

事件流:描述从页面中接收事件的顺序。

(1)事件冒泡 ⭐️

事件冒泡(event bubbling):事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
所有现代浏览器都支持事件冒泡。
实现差别:IE5.5 及更早版本中的事件冒泡会跳过<html>元素,IE9、Firefox、Chrome 和 Safari 将事件一直冒泡到 window 对象。

(2)事件捕获

事件捕获(event capturing):不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。
IE9、Safari、Chrome、Opera 和 Firefox 目前都支持这种事件流模型。这些浏览器都是从 window 对象开始捕获事件的。
有特殊需要时再使用事件捕获。

(3)DOM事件流

事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。
在这里插入图片描述
IE9、Opera、Firefox、Chrome 和 Safari 都支持 DOM 事件流。

2. 事件处理程序

事件处理程序(事件侦听器):响应某个事件的函数,以"on"开头

(1)HTML事件处理程序

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

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

以下字符需要转义:和号(&)、双引号("")、小于号(<) 或大于号(>)。

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

<input type="button" value="Click Me" onclick="showMessage()" />

函数中有一个局部变量 event,可以直接访问事件对象。
函数内部,this 值等于事件的目标元素。

<input type="button" value="Click Me" onclick="alert(event.type)">
<input type="button" value="Click Me" onclick="alert(this.value)">

扩展作用域的方式:
函数内部,可以像访问局部变量一样访问 document 及该元素本身的成员。
如果当前元素是一个表单输入元素,则作用域中还会包含访问表单元素(父元素)的入口。

function(){
  with(document){
    with(this.form){
      with(this){ 
        //元素属性值
      }
    }
  }
}

缺点:
1.存在一个时差问题。因为用户可能会在 HTML 元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。 – > try-catch
2.这样扩展事件处理程序的作用域链在不同浏览器中会导致不同结果。不同 JavaScript 引擎遵循的标识符解析规则略有差异,很可能会在访问非限定对象成员时出错。
3.HTML 与 JavaScript 代码紧密耦合。如果要更换事件处理程序,就要改动两个地方:HTML 代码和 JavaScript 代码。
结论:许多开发人员摒弃 HTML 事件处理程序,转而使用 JavaScript 指定事件处理程序。

(2)DOM0 级事件处理程序

通过 JavaScript 指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。
每个元素(包括 window 和 document)都有自己的事件处理程序属性,这些属性通常全部小写(onclick),这种属性的值设置为一个函数,就可以指定事件处理程序。

btn.onclick = function(){
    alert(this.id);
};

使用 DOM0 级方法指定的事件处理程序,是在元素的作用域中运行,程序中的 this 引用当前元素
以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。

删除通过 DOM0 级方法指定的事件处理程序:

btn.onclick = null; //删除事件处理程序
(3)DOM2 级事件处理程序

“DOM2 级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:
addEventListener()removeEventListener()
参数:要处理的事件名,作为事件处理程序的函数,一个布尔值 (true在捕获阶段调用事件处理程序,false在冒泡阶段调用事件处理程序)

btn.addEventListener("click", function(){
  alert(this.id);
}, false);
btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false);

事件处理程序是在其依附的元素的作用域中运行,this 引用当前元素。

优势:可以添加多个事件处理程序。

注意:
通过 addEventListener() 添加的事件处理程序只能使用 removeEventListener()来移除。
通过 addEventListener() 添加的匿名函数将无法移除。(移除时没有对应的函数名)

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

(4)IE事件处理程序

IE 实现了与 DOM 中类似的两个方法:attachEvent()detachEvent()
两个参数:事件处理程序名称,事件处理程序函数。
该方式只会被添加到冒泡阶段(IE8及更早版本只支持事件冒泡)。

btn.attachEvent("onclick", function(){
  alert("Clicked");
});
btn.attachEvent("onclick", handler);
btn.detachEvent("onclick", handler);

attachEvent()与DOM方法比较:

  • attachEvent() 第一个参数是"onclick",addEventListener() 方法中是"click"。
  • 与DOM0级方法主要区别:事件处理程序的作用域。
    DOM0级方法,事件处理程序在其所属元素的作用域内运行;attachEvent()方法,事件处理程序会在全局作用域中运行,因此 this 等于 window。
  • 也可以用来为一个元素添加多个事件处理程序。
    与DOM方法不同,调用两次attachEvent(),这些事件处理程序不是以添加它们的顺序执行,而是以相反的顺序被触发。
  • 使用 attachEvent() 添加的事件可以通过 detachEvent() 来移除,同样,添加的匿名函数将不能被移除。

浏览器支持:IE 和 Opera。

(5)跨浏览器的事件处理程序

addHandler():视情况分别使用 DOM0 级方法、DOM2 级方法 或 IE 方法来添加事件。
这个方法属于一个 EventUtil 对象(使用这个对象来处理浏览器间的差异)。
3 个参数:要操作的元素,事件名称,事件处理程序函数。

removeHandler():移除之前添加的事件处理程序——无论该事件处理程序是采取什么方式添加到元素中的,如果其他方法无效,默认采用 DOM0 级方法。
参数同上。

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;
    }
  }
};

注意:addHandler() 和 removeHandler() 没有考虑到所有的浏览器问题,例如在 IE 中的作用域问题。不过使用它们添加和移除事件处理程序已经足够。


上一篇:28-JavaScript高级程序设计-DOM2&3范围
下一篇:30-JavaScript高级程序设计-事件对象

全书整理版:《Javascript高级程序设计》第3版(总结版)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值