本文首发于公众号:符合预期的CoyPan
事件并非JavaScript
的核心部分,他们是在浏览器的Web Api
中定义的。下面列举的几种状况,都属于发生了事件。javascript
咱们能够在代码中使用事件处理器
来处理各类事件。html
假设咱们有这么一段html
代码:前端
<html> <body> <table> <tbody> <tr> <td>Shady Grove</td> <td>Aeolain</td> </tr> <tr> <td>Over the River, Charile</td> <td>Dorian</td> </tr> </tbody> </table> </body> </html>
若是咱们点击over the Rive, Charile
,整个事件流程以下:java
事件会经历三个阶段,上图中分别由红色、蓝色、绿色标出。第一阶段为红色,事件流从根元素一直走到点击的目标元素,这个过程称为捕获
。第二阶段为蓝色, 称为目标阶段。这个阶段中,会处理点击事件,为事件加上各类属性等。第三阶段为绿色,事件又回从新回到根元素,这个过程称为冒泡
。在整个事件流中,咱们在事件流通过的任何元素上,都能监听到该事件,从而进行处理。node
通常建议在冒泡阶段处理事件,这样能够最大限度的兼容各类浏览器。web
注意:blur、focus、load、unload 等几个事件不会冒泡。缘由是在于:这些事件仅发生于自身上,而它的任何父节点上的事件都不会产生,全部不会冒泡。浏览器
咱们能够查看事件的bubbles属性,来判断该事件是否能够冒泡。函数
EventTarget
是一个由能够接收事件的对象实现的接口,而且能够为它们建立侦听器。Web中的全部事件处理器都是由EventTarget
"提供"的。性能
该方法将指定的监听器注册到 EventTarget
上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标能够是一个文档上的元素 Element
,Document
和Window
或者任何其余支持事件的对象 (好比 XMLHttpRequest
)。其标准语法以下:spa
target.addEventListener(type, listener[, options]); target.addEventListener(type, listener[, useCapture]);
listener:函数。事件触发时的回调函数。这个函数会接受一个Event
事件对象。这个Event
事件对象中,包含了如下重要的属性和方法(这里只列举出经常使用的)
属性 | 值 |
---|---|
bubbles | 只读。一个布尔值,表示该事件是否可以在DOM中冒泡。 |
cancelBubble | 经过在一个事件处理程序返回前设置这个属性的值为真,来阻止事件冒泡。 |
cancelable | 只读。一个布尔值,用来表示这个事件是否能够取消。 |
currentTarget | 只读。注册事件监听的对象。 |
target | 只读。对事件起源目标的引用。 |
方法 | 做用 |
---|---|
preventDefault | 取消默认事件 |
stopPropagation | 阻止事件冒泡 |
options :对象。指定一个listener
的配置参数。
属性 | 值 |
---|---|
capture | 布尔值。若是为true,表示该listener会在捕获过程当中执行。若是为false,listener会在冒泡过程当中执行。默认为false。 |
once | 布尔值。默认为false。若是为true,listener只会执行一次,而且执行后会被自动移除。 |
passive | 布尔值。若是为true,则没法调用preventDefault来阻止默认事件。默认为false。这个属性有一个须要注意的地方。在safari浏览器的页面滚动事件中,这个值是默认的true。因此要阻止safari中的页面滚动,须要手动将这个值设为false。 |
false
,事件在冒泡过程当中触发listener
。删除使用addEventListener
注册到target
上的事件。标准语法:
target.removeEventListener(type, listener[, options]); target.removeEventListener(type, listener[, useCapture]);
为了提升页面性能,咱们在处理完某事件,而且不用继续监听该事件时,能够将以前注册的事件监听函数移除。须要注意的是,若是注册事件时,在捕获或冒泡阶段均进行了监听,那么移除时须要分别移除。
在事件处理函数中,咱们常常会使用到事件的这两个属性。currentTarget
表示注册事监听的对象。target
表示事件起源的对象。举个例子:
<div id="father"> <div id="child1">child1</div> <div id="child2">child2</div> <div id="child3">child3</div> </div> document.getElementById('father').addeventListener('click', function(e){ console.log(e.currentTarget); console.log(e.target); });
咱们将事件处理函数绑定在father
上。如今,若是咱们点击的是child1
,因为child1
是事件源,那么e.target
就是child1
。而咱们的事件处理函数是绑定在father
上的,因此,e.currentTarget
就是father
。
这一点在开发过程当中须要特别注意。
这个概念依赖于这样一个事实,若是你想要在大量子元素中单击任何一个均可以运行一段代码,您能够将事件监听器设置在其父节点上,并将事件监听器气泡的影响设置为每一个子节点,而不是每一个子节点单独设置事件监听器。举个例子:
<ul> <li>1<li> <li>2<li> <li>3<li> <li>4<li> <li>5<li> <li>6<li> <li>7<li> <li>8<li> <li>9<li> </ul>
咱们要实现点击每个li
的时候,输出li
内对应的数字,咱们固然能够直接在全部的li
上分别绑定一个事件。可是这样会形成内存的浪费。咱们能够只在ul
上绑定一个事件,根据事件的target
来获取当前点击的li
,拿到该li
内对应的数字。
document.querySelector('ul').addEventListener('click', function(e){ if(e.target && e.target.nodeName === "LI") { console.log(e.target.innerHTML); } });
最新的DOM
标准容许咱们自定义事件。直接看下面的例子。
var fakeNode = document.createElement('Coy'); // 建立一个自定义元素 var evt = document.createEvent('Event'); // 建立一个自定义事件 var evtType = 'test'; // 自定义事件的类型 // 事件监听函数 fakeNode.addEventListener(evtType, function(e){ console.log(e); // e.type === 'test'; }, false); // 初始化事件。 // initEvent用法:event.initEvent(type, bubbles, cancelable); evt.initEvent(evtType, false, false); // 向fakeNode派发evt事件 fakeNode.dispatchEvent(evt);
事件,是前端开发中的一个基础。虽然简单,可是十分重要。
欢迎关注个人公众号: 符合预期的CoyPan
作一名符合预期的FE