JavaScript事件处理下

JavaScript注册事件处理下

注册事件处理程序有两种基本方式,第一种是给目标对象或文档元素设置属性。第二种更为通用,是将事件处理程序传递给对象或元素的一个方法。

可以在 JavaScript 代码中设置事件处理程序的对象属性,或对于文档流元素,可以在 HTML 中直接设置相应属性。对于通过方法调用的处理程序注册,有个标准方法 addEventListenter()IE8 及以前版本的之外都支持,在 IE9 之前有个另一个方法 attachEvent()

设置 JavaScript 对象属性为事件处理程序

注册事件处理程序最简单的方式就是通过设置事件目标的属性为所需事件处理程序函数。区分大小写,并且都是小写,如 onclick、onchange、onload、onmouseover

1
2
3
4
5
//设置window 对象的 unload 属性为一个函数
//当文档加载完毕时调用它
window.onload = function () {
//...
}

一般情况下,所有广泛实现的 Web API 定义的事件都允许通过设置事件处理程序属性来注册事件处理程序。

缺点是每个事件目标对于每种事件类型将最多只有一个处理程序,如果想要编写能再任意文档中使用的脚本库代码,更好的方式是使用一种不修改或者覆盖任何已有注册事件程序的技术,例如 addEventListenner()

设置 HTML 标签属性为事件处理程序

1
<button onclick="alert('THANK YOU!')"></button>

这里有几个特点:

  • 属性值是 JavaScript 代码字符串
  • 这段代码是处理程序函数的主题,而非完整的函数声明
  • 不应该使用大括号包裹和 function 关键字作为前缀
  • 多条语句用 ; 隔开

addEventListener()

注意前面提到的兼容性问题。

Window对象、Document 对象和所有文档元素都可以使用 addEventListener()

语法

1
target.addEventListener(type, listener[, options]);
1
2
3
4
5
6
7
8
9
10
11
12
13
// 改变t2的函数
function modifyText() {
var t2 = document.getElementById("t2");
if (t2.firstChild.nodeValue == "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
}
}

// 为table添加事件监听器
var el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);

removeEventListener()

删除使用 EventTarget.addEventListener() 方法添加的事件

1
2
3
4
5
6
var div = document.getElementById('div');
var listener = function (event) {
/* do something here */
};
div.addEventListener('click', listener, false);
div.removeEventListener('click', listener, false);

attach……Event()

这是早期IE浏览器(IE8及早期版本)的一个专有的替代性标准,替代 EventTarget.addEventListener() 方法

⚠️ 非标准 该特性是非标准的,请尽量不要在生产环境中使用它!
HEXO中不能出现此方法,会报错导致页面无法显示

  • 因为IE 模型不支持事件捕获,所以只有两个参数:事件类型和处理函数
  • 带on前缀,要给该方法传递 ‘onclick’
  • 允许相同事件注册多次,也会被调用多次

事件处理程序的调用

本节也会说明事件的传播机制,即单个事件如何能在原始目标和文档容器上触发多个处理程序的调用。

事件处理程序的参数

通常调用事件处理程序时会把事件对象作为它们的一个参数,提高有关事件的详细信息。

一个 IE8 以前版本中,获取事件对象

1
2
3
function handler(event){
event = event || window.event;
}

事件处理程序的运行环境

1
e.onclick = function(){/* 处理程序代码 */}
  • 在事件处理程序中,this 关键字指的是事件目标
  • 当使用 addEventListener() 注册时,也是一样
  • 但对于 attachEvent()this 却是 全局对象 Window,兼容的方法在书中有举例

事件处理程序返回值

通常情况下,返回 false 就是告诉浏览器不要执行这个事件相关的默认操作

window.onbeforeunload() : 当浏览器将要跳转到新页面时触发,如果返回一个字符串,那么将会出现在询问用户是否离开当前页面的标准对话框中(有兼容性问题,并不是所有浏览器都可以自定义提示信息,更多是浏览器标准提示)。

1
2
3
4
5
6
7
8
9
10
11
window.onbeforeunload = function (e) {
e = e || window.event;

// 兼容IE8和Firefox 4之前的版本
if (e) {
e.returnValue = '关闭提示';
}

// Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
return '关闭提示';
};

调用顺序

  • 通过设置对象属性或 HTML 属性注册的处理程序一直优先调用
  • 使用 addEventListener() 注册的处理程序按照它们的注册顺序调用
  • 使用 attachEvent() 注册的处理程序可能按照任何顺序调用,所有代码不应该依赖于调用顺序

事件传播

当事件目标是 Window 对象或其他一些单独对象(比如 XMLHttpRequest )时,浏览器简单通过调用对象上适当的处理程序响应事件。

但当事件目标是文档或文档元素时,情况较为复杂。

大部分的事件都会“冒泡”到 DOM 树根,层层向上传递,事件冒泡为在大量单独文档元素上注册处理程序提供了代替方案,即在共同的祖先元素上注册一个处理程序来处理所有事件。

📍 事件传播的三个阶段:

  • 第一阶段发生在目标处理程序调用之前,称为 “捕获”阶段,回顾上文 addEventListener() 的第三个参数,注意兼容性问题
  • 第二阶段是目标对象本身的事件处理程序的调用
  • 第三阶段是事件冒泡

事件捕获提供了在事件没有送达目标之前查看他们的机会。能用于程序调试、事件取消技术过滤掉事件从而使目标事件程序绝不会被调用、处理鼠标拖放

事件取消

在支持 addEventListener() 的浏览器中,可以通过调用事件对象的 preventDefaultDefault() 方法取消事件的默认操作, IE9 之前,可以通过设置事件对象的 returnValue 属性为 false 达到相同效果。

在支持 addEventListener() 的浏览器中,stopPropagation() 方法阻止事件的继续传播,IE9 之前, 使用 cancelBubble()

具体的事件类别

至此,已经学习了 JavaScript 事件处理的基本原理,针对于具体的事件,请查阅犀牛书相关章节

  • 文档加载事件
  • 鼠标事件
  • 鼠标滚轮事件
  • 拖放事件
  • 文本事件
  • 键盘事件