# Event 对象 ## 概述 事件发生以后,会产生一个事件对象,作为参数传给监听函数。浏览器原生提供一个`Event`对象,所有的事件都是这个对象的实例,或者说继承了`Event.prototype`对象。 `Event`对象本身就是一个构造函数,可以用来生成新的实例。 ```javascript event = new Event(type, options); ``` `Event`构造函数接受两个参数。第一个参数`type`是字符串,表示事件的名称;第二个参数`options`是一个对象,表示事件对象的配置。该对象主要有下面两个属性。 - `bubbles`:布尔值,可选,默认为`false`,表示事件对象是否冒泡。 - `cancelable`:布尔值,可选,默认为`false`,表示事件是否可以被取消,即能否用`Event.preventDefault()`取消这个事件。一旦事件被取消,就好像从来没有发生过,不会触发浏览器对该事件的默认行为。 ```javascript var ev = new Event( 'look', { 'bubbles': true, 'cancelable': false } ); document.dispatchEvent(ev); ``` 上面代码新建一个`look`事件实例,然后使用`dispatchEvent`方法触发该事件。 注意,如果不是显式指定`bubbles`属性为`true`,生成的事件就只能在“捕获阶段”触发监听函数。 ```javascript // HTML 代码为 //
Hello
Hello World
function hide(e) { console.log(this === e.currentTarget); // 总是 true console.log(this === e.target); // 有可能不是 true e.target.style.visibility = 'hidden'; } para.addEventListener('click', hide, false); ``` 上面代码中,如果在`para`节点的``子节点上面点击,则`e.target`指向``子节点,导致``子节点(即 World 部分)会不可见。如果点击 Hello 部分,则整个`para`都将不可见。 ### Event.type `Event.type`属性返回一个字符串,表示事件类型。事件的类型是在生成事件的时候指定的。该属性只读。 ```javascript var evt = new Event('foo'); evt.type // "foo" ``` ### Event.timeStamp `Event.timeStamp`属性返回一个毫秒时间戳,表示事件发生的时间。它是相对于网页加载成功开始计算的。 ```javascript var evt = new Event('foo'); evt.timeStamp // 3683.6999999995896 ``` 它的返回值有可能是整数,也有可能是小数(高精度时间戳),取决于浏览器的设置。 下面是一个计算鼠标移动速度的例子,显示每秒移动的像素数量。 ```javascript var previousX; var previousY; var previousT; window.addEventListener('mousemove', function(event) { if ( previousX !== undefined && previousY !== undefined && previousT !== undefined ) { var deltaX = event.screenX - previousX; var deltaY = event.screenY - previousY; var deltaD = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); var deltaT = event.timeStamp - previousT; console.log(deltaD / deltaT * 1000); } previousX = event.screenX; previousY = event.screenY; previousT = event.timeStamp; }); ``` ### Event.isTrusted `Event.isTrusted`属性返回一个布尔值,表示该事件是否由真实的用户行为产生。比如,用户点击链接会产生一个`click`事件,该事件是用户产生的;`Event`构造函数生成的事件,则是脚本产生的。 ```javascript var evt = new Event('foo'); evt.isTrusted // false ``` 上面代码中,`evt`对象是脚本产生的,所以`isTrusted`属性返回`false`。 ### Event.detail `Event.detail`属性只有浏览器的 UI (用户界面)事件才具有。该属性返回一个数值,表示事件的某种信息。具体含义与事件类型相关。比如,对于`click`和`dblclick`事件,`Event.detail`是鼠标按下的次数(`1`表示单击,`2`表示双击,`3`表示三击);对于鼠标滚轮事件,`Event.detail`是滚轮正向滚动的距离,负值就是负向滚动的距离,返回值总是3的倍数。 ```javascript // HTML 代码如下 //Hello
function giveDetails(e) { console.log(e.detail); } document.querySelector('p').onclick = giveDetails; ``` ## 实例方法 ### Event.preventDefault() `Event.preventDefault`方法取消浏览器对当前事件的默认行为。比如点击链接后,浏览器默认会跳转到另一个页面,使用这个方法以后,就不会跳转了;再比如,按一下空格键,页面向下滚动一段距离,使用这个方法以后也不会滚动了。该方法生效的前提是,事件对象的`cancelable`属性为`true`,如果为`false`,调用该方法没有任何效果。 注意,该方法只是取消事件对当前元素的默认影响,不会阻止事件的传播。如果要阻止传播,可以使用`stopPropagation()`或`stopImmediatePropagation()`方法。 ```javascript // HTML 代码为 // var cb = document.getElementById('my-checkbox'); cb.addEventListener( 'click', function (e){ e.preventDefault(); }, false ); ``` 上面代码中,浏览器的默认行为是单击会选中单选框,取消这个行为,就导致无法选中单选框。 利用这个方法,可以为文本输入框设置校验条件。如果用户的输入不符合条件,就无法将字符输入文本框。 ```javascript // HTML 代码为 // var input = document.getElementById('my-input'); input.addEventListener('keypress', checkName, false); function checkName(e) { if (e.charCode < 97 || e.charCode > 122) { e.preventDefault(); } } ``` 上面代码为文本框的`keypress`事件设定监听函数后,将只能输入小写字母,否则输入事件的默认行为(写入文本框)将被取消,导致不能向文本框输入内容。 ### Event.stopPropagation() `stopPropagation`方法阻止事件在 DOM 中继续传播,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上其他的事件监听函数。 ```javascript function stopEvent(e) { e.stopPropagation(); } el.addEventListener('click', stopEvent, false); ``` 上面代码中,`click`事件将不会进一步冒泡到`el`节点的父节点。 ### Event.stopImmediatePropagation() `Event.stopImmediatePropagation`方法阻止同一个事件的其他监听函数被调用,不管监听函数定义在当前节点还是其他节点。也就是说,该方法阻止事件的传播,比`Event.stopPropagation()`更彻底。 如果同一个节点对于同一个事件指定了多个监听函数,这些函数会根据添加的顺序依次调用。只要其中有一个监听函数调用了`Event.stopImmediatePropagation`方法,其他的监听函数就不会再执行了。 ```javascript function l1(e){ e.stopImmediatePropagation(); } function l2(e){ console.log('hello world'); } el.addEventListener('click', l1, false); el.addEventListener('click', l2, false); ``` 上面代码在`el`节点上,为`click`事件添加了两个监听函数`l1`和`l2`。由于`l1`调用了`event.stopImmediatePropagation`方法,所以`l2`不会被调用。 ### Event.composedPath() `Event.composedPath()`返回一个数组,成员是事件的最底层节点和依次冒泡经过的所有上层节点。 ```javascript // HTML 代码如下 //Hello
//