本文采用升级的方式, 由最简单的事件概念到对于 DOM 事件的全面了解.
第一: 什么是事件
事件不是一个需要严格定义的技术名词. 简单理解, 事件就是文档或浏览器窗口中发生的交互 (或动作). 比如点击或拖动一个元素, 文档加载完成, Ajax 中的 onreadystatechange 事件等.
事件发生并不会导致后续行为, 只有在事件具有了对应的事件处理程序, 才会在事件发生时产生后续的响应行为. 就像「如果今天天气不错」和「如果今天天气不错, 我们去打球」这两句话, 前者只是事件发生, 后者才是在事件发生时执行响应的行为.
第二: 事件处理程序
有三种方式可以在一个 DOM 元素上添加事件处理程序.
在 html 标签中设置事件同名属性
<input type="button" onclick="alert('Hello world!')">
代码中 onclick 的值应该为可执行的 JavaScript 语句, 如果是多条语句可以用分号隔开.
设置元素事件处理程序属性 (DOM0 级事件)
Windows,document 和所有文档元素都有自己的事件处理程序属性, 这些属性都是小写. 将元素属性的值设置为一个函数, 这个函数就是元素的事件处理程序. 具体代码如下:
- let nav = document.querySelector('nav');
- nav.onclick = function() {
- alert(this.nodeName); // 此处 this 引用当前元素, 结果为 nav
- }
这种方法的缺点是只能设置一个处理程序.
通过 addEventListener 函数添加事件处理程序 (DOM2 级事件)
- element.addEventListener('click', function (event) {
- alert(event.currentTarget.nodeName); // 输出当前元素的标签名
- }, false);
这个函数有三个参数, 第一个参数是事件类型, 第二个参数是事件处理程序, 第三个参数是设置事件触发的阶段. 默认值为 false, 表示事件在冒泡阶段触发. 具体区别在讲解事件流时说明.
关于 DOM2 级事件还有一个方法是 removeEventListener, 用于删除事件处理程序.
只有参数与 addEventListener 相同, removeEveneListener 才会发挥作用, 也就是说如果第二个参数是一个匿名函数, 事件删除不会成功.
注意: Internet Explorer 9 之前并不支持这个方法, 有一个类似的方法 element.attachEvent.
第三: 事件类型
事件可以分为 UI 事件, 焦点事件, 鼠标事件, 滚轮事件, 文本事件, 键盘事件, 合成事件, 变动事件以及 HTML5 事件.<audio> 和 <video> 的事件属于 HTML5 事件.
第四: 事件流是什么
首先来回答事件流是什么. 事件流就是从页面中接收事件的顺序, 或者事件在页面上传递的顺序.
这个概念可以这么理解. 当你单击了一个元素, 这个元素触发单击事件. 有时这个元素外面有一层父元素, 父元素之外或许还有一层父元素. 那么子元素触发单击事件, 父元素会怎么样呢?
浏览器的开发团队规定, 触发事件元素的父元素也触发了事件, 父元素的父元素也触发了事件. 此时就产生了一个顺序问题, 是先触发父元素事件再触发子元素事件, 还是先触发子元素事件再触发父元素事件. 这两种触发方式都有自己实现, 先父后子称为事件捕获, 先子后父称为事件冒泡.
DOM2 级事件流分为三个阶段, 事件捕获阶段, 目标阶段和事件冒泡阶段. 也就是 事件先从 Windows 对象一级一级传到目标元素, 在从目标元素传到 Windows 对象. 就像下图所示:
事件流
addEventListener 函数的第三个参数, 用来设置事件的触发是在事件捕获阶段还是在事件冒泡阶段.
具体验证代码如下:
- <table>
- <tbody>
- <tr>
- <td></td>
- <td></td>
- </tr>
- <tr>
- <td></td>
- <td></td>
- </tr>
- </tbody>
- </table>
- <script>
- let td = document.querySelector('td')
- Windows.addEventListener("click", function () {
- alert("捕获 window");
- }, true);
- document.addEventListener("click", function () {
- alert("捕获 document");
- }, true);
- document.documentElement.addEventListener("click", function () {
- alert("捕获 html");
- }, true);
- document.body.addEventListener("click", function () {
- alert("捕获 body");
- }, true);
- td.addEventListener("click", function (event) {
- alert(event.target.nodeName);
- }, true);
- </script>
将 addEventListener 的第三个参数改为 false 验证事件冒泡.
第五: event 参数怎么用? 如何自定义事件
addEventListener 的事件处理程序有一个参数, 一般将参数命名为 event, 就像上方代码那样.
event 常用属性, 下面我依次列举.
event.stopPropagation()
这是一个函数, 调用后阻止事件的冒泡传递. 也就是说, 如果子元素的处理程序内调用了该方法, 父元素不会触发该事件.
event.preventDefault()
阻止默认事件, 比如在 <a > 的处理函数中调用这个方法, 就会阻止链接的默认跳转.
event.currentTarget: 事件处理程序当前正在处理事件的那个元素, 即当前事件处理函数绑定的元素.
event.target: 事件的目标, 比如你点击或触摸的元素.
自定义事件以具体代码为例:
- let eve = new Event('cT')
- // 自定义事件一般与其他事件结合使用
- document.body.addEventListener('cT',function(event) {
- console.log('666')
- },false)
- setTimeout(function() {
- document.body.dispatchEvent(eve) // 触发自定义事件
- },1000)
如果文章对你有帮助, 请点个赞支持一下.
Octavio Fossatti 2015-10-05 08-34-58 .jpg
来源: http://www.jianshu.com/p/9cbd9559cee5