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);