DOM事件监听和触发
EventTargetAPI定义了DOM事件(mouse事件等)的监听和触发方法,所有的DOM节点都部署了这个接口。
这个接口有三个方法:addEventListener, removeEventListener, dispatchEvent。
一. EventTargetAPI
1. EventTarget.addEventListener(type, listener, options)
给DOM节点对象添加事件监听。
语法:
eleTarget.addEventListener(type, listener [, useCapture]) // type: DOM事件类型,区分大小写 // listener: 监听回调函数,function(e){}; e是事件发生产生的Event对象; // userCapture: 布尔值,是否在捕获阶段触发;相当于{capture: boolean}
第二个参数,是个回调函数,入参是Event对象,内部的this, 指向DOM节点对象eleTarget.
<button id="btn">ClickMe</button> <script> btn.addEventListener('click',function(e) { console.log(this === btn); // true }) </script>
第三个参数还可以是一个配置对象:
eleTarget.addEventListener(type, listener, options) // options的属性如下: options = { capture: boolean, // 是否在捕获阶段触发;默认false once: boolean, // 是否只监听一次,然后自动移除;默认false, passive: boolean, // 是否禁止prentDefault()方法;默认false }
为同一个目标添加同一个监听事件,如果回调函数相同,那么只执行一次,其余的忽略。
function hello() { console.log('Hello world'); } document.addEventListener('click', hello, false); document.addEventListener('click', hello, false); //自动忽略 // 运行结果 hello world
为同一个目标添加同一个监听事件,如果回调函数不同,那么按照添加顺序,依次执行。
function hello() { console.log('Hello'); } function world() { console.log('world') } document.addEventListener('click', hello, false); document.addEventListener('click', world, false); // 运行结果 hello world
这点和DOM对象的on[event]事件不同,on[Event]会出现覆盖,只最后一个起作用;
而且只在冒泡阶段触发,不能指定触发的阶段。
function hello() { console.log('Hello'); } function world() { console.log('world') } document.onclick = hello; document.onclick = world; // 运行结果 world
另外,HTML的on[event]事件,引号内是可执行JS代码
<div onclick="hello()">ClickMe</div>
2. EventTarget.removeEventListener(type, listener, options)
语法:
function hello() { console.log("hello"); } element.addEventListener('click', hello, true); element.removeEventListener('click', hello, true); //注意 // remove方法作用的element和后面的参数必须完全一致。 // 且第二个参数必须是函数的变量形式传递;否则,相当于一个新的函数,即使内容和add中一样,也是一个新的函数
3. EventTarget.dispatch(event)
手动触发监听函数,通过代码触发;
参数不能为空,必须是Event对象;
返回一个布尔值,表示是否触发成功; 返回值在监听函数执行完成后返回。
示例:
btn.addEventListener('click',function(event) { console.log('listener end') }) console.log(btn.dispatchEvent(new Event('click'))); // 运行结果如下: listener end true
应用:
可以自定义一个事件监听函数,在需要的位置触发函数调用。
btn.addEventListener('lyra',function(event) { console.log('Be dispatched at i=2') }) btn.addEventListener('myevent',function(event) { console.log('Be dispatched at i=1') }) for(let i=0; i < 10; i++) { if (i === 1) { btn.dispatchEvent(new Event('myevent')); } if (i === 2) { btn.dispatchEvent(new Event('lyra')); } } // 运行结果 Be dispatched at i=1 //i===1时先触发myevent Be dispatched at i=2
二. Event事件
上面的监听和触发函数的基础是Event对象。
Event是js的原生对象,每个DOM事件产生的对象都是它的实例。
它是一个构造函数,实例化可以自定义一个事件。
语法如下:
const event = new Event(type, options); // type是自定义事件的类型 // options是自定义事件的配置
options有两个属性:
const options = { bubbles: boolean, // 指定事件是否可以冒泡;默认false,只在捕获阶段触发 cancelable: boolean, // 指定事件是否可以调用preventDefault()方法 }
三. CustomEvent事件
和Event事件的构造函数的区别是: 触发时可以通过detail属性传入自定义数据。
const data = fetch(url); const event = new CustomEvent('myevent', { bubbles: false, cancelable: false, detail: data }) ele.addEventListener('myevent', function(e){ console.log(e.detail); //data }) ele.dispatch(event)
四.应用
DOM节点同时绑定单击事件和双击事件
let previous=0; let timer; btn.addEventListener('click', function(e) { const diff = e.timeStamp - previous; if (diff < 300) {// 双击 console.log('double click'); clearTimeout(timer); } else { timer = setTimeout(function() { console.log('single click') },300); previous = e.timeStamp; } },false);