DOM0
html標簽中的寫法
"element" src="hello.png" onclick="alert('Hi')"/>
復制代碼
在JS中的綁定方法:
var element = document.getElementById("element");
element.onclick = function(e) {}
復制代碼
dom0是節點元素的私有屬性。愛掏網 - it200.com同一個事件只能綁定一個,綁定多個,只有最后一個有效。愛掏網 - it200.com直接寫在html節點上的也會被覆蓋。愛掏網 - it200.com如下面的代碼,最后點擊觸發的時候只會打印3。愛掏網 - it200.com
var element = document.getElementById("element");
element.onclick = function(e) {console.log(1)};
element.onclick = function(e) {console.log(2)};
element.onclick = function(e) {console.log(3)};
復制代碼
所以,在使用如window.onload
之類的事件的時候就需要注意了。愛掏網 - it200.com
DOM1
有標準,不涉及實踐。愛掏網 - it200.com
DOM2
addEventListener
方法在節點對象的原型鏈上。愛掏網 - it200.com綁定實名函數更好,因為可以移除。愛掏網 - it200.com第三個參數用于選擇在什么階段觸發,默認false表示在冒泡階段觸發。愛掏網 - it200.com
element.addEventListener('change',function(){},false)
復制代碼
與DOM0的相比,DOM2事件可以綁定多個,如下,1和2都會被打印:
element.addEventListener('change', function() {console.log(1)}, false);
element.addEventListener('change', function() {console.log(2)}, false);
復制代碼
可是,在綁定實名函數的時候,如果事件、函數名和觸發階段完全相同的話,最終也是只有最后一個有效,如下,最終事件觸發的時候只會打印出一個1:
function fn() {console.log(1)};
element.addEventListener('change', fn, false);
element.addEventListener('change', fn, false);
復制代碼
此外,addEventListener
還可以綁定DOM0中沒有的事件,如DOMContentLoaded。愛掏網 - it200.com
DOM3
與DOM2的區別在于事件的種類,其他的一樣。愛掏網 - it200.com如keyup
、keydown
、keypress
都是DOM3的事件,click
也是DOM3級事件,具體到MDN中搜索DOM L3
。愛掏網 - it200.com
事件流
簡要的說就是事件的三個階段:捕獲階段--目標階段--冒泡階段。愛掏網 - it200.com詳細說就是如下圖。愛掏網 - it200.com
當用戶點擊瀏覽器窗口,事件發生,捕獲階段開始:window--document--html--body--父節點--目標節點(目標階段),然后開始冒泡階段:目標節點--父節點--body--html--document--window。愛掏網 - it200.com
幾個需要注意的api:
preventDefault的作用是阻止瀏覽器默認行為,什么是默認行為?除了你自己綁定的操作之外的行為都是瀏覽器的默認行為,如a標簽的跳轉,表單的提交,鼠標右鍵呼出菜單等等。愛掏網 - it200.com
此外event.returnValue = false;
、return false;
也可以達到跟proventDefault
同樣的效果。愛掏網 - it200.com如果是a標簽,阻止跳轉,可以href="javascript:;"
或href=javascript:void 0;
stopPropagation的作用是阻止事件的傳播。愛掏網 - it200.com阻止的是其他節點上的事件。愛掏網 - it200.com
stopImmediatePropagation的作用也是阻止事件的傳播。愛掏網 - it200.com它不但能阻止其他節點上的事件,當前節點上的其他未觸發的事件也會一并阻止。愛掏網 - it200.com如下代碼,只打印1:
element.addEventListener('click', function(event) {
event.stopImmdiatePropagation();
console.log(1);
}, false);
element.addEventListener('click', function() {console.log(2)}, false);
復制代碼
currentTarget,當前會執行的回調函數綁定的那個節點。愛掏網 - it200.com
elementFirst.addEventListener('click', function(event) {
console.log(event.currentTarget); // elementFirst
}, false);
elementSecond.addEventListener('click', function(event) {
console.log(event.currentTarget); // elementSecond
}, false);
復制代碼
target,就是事件流中的目標階段的那個節點,也就是目標節點。愛掏網 - it200.com需要注意的是,事件是否發生與是否綁定的操作沒有關系,即便沒有在一個節點上綁定事件的操作,事件依然會發生。愛掏網 - it200.comtarget
可以在事件委托中使用。愛掏網 - it200.com
自定義事件
var myEvent = new Event('theEvent');
theTarget.addEventlistener('theEvent', function() {doSomething()})
theTarget.dispatchEvent(myEvent); // theTarget是一個節點,或者說是一個可以調用addEventListener方法的對象。愛掏網 - it200.com
復制代碼
此外customEvent
做到跟Event
同樣的效果,他們的區別在于,customEvent
可以加一些自己需要的數據進去,不過兼容性沒有Event
好。愛掏網 - it200.com
用Event
創建了實例之后,也可以用myEvent.data = {}
的方式給數據,效果是一樣的。愛掏網 - it200.com
這有什么用?可以用來做全局范圍內的廣播,使模塊間解耦。愛掏網 - it200.com在vue中有一個用于組件間通訊的EventBus,自定義事件就可以用來實現這一功能。愛掏網 - it200.com
事件委托和代理
事件委托就是把本來應該由你來做的事情,讓別人幫忙做一下。愛掏網 - it200.com
在實際編程中,可能會出現這樣的場景,一個節點下有多個子節點,每個子節點都要有相應的事件綁定,這個時候我們就可以利用事件的冒泡,把事件綁定在父節點上,然后用event.target
來區分到底是哪個子節點觸發的事件。愛掏網 - it200.com當這些子節點需要動態增減的時候,使用事件委托就顯得尤為方便了,無論是寫代碼的效率還是程序運行的效率都會更高。愛掏網 - it200.com
局限性:focus、blur這樣的事件沒有在冒泡機制,無法委托。愛掏網 - it200.com另外一些消耗較高的事件如mousemove和mouseout也不適合委托。愛掏網 - it200.com如下圖
如果我們把B區域的mousemove事件委托到A區域,當事件在A區域發生的時候,對應的操作也會執行,如果是消耗較低的事件,就不會有太大的影響,可如果是消耗較高的事件,就會顯得有點浪費了。愛掏網 - it200.com
觀察者模式與發布訂閱模式
這兩種設計模式與事件非常的類似。愛掏網 - it200.com與事件的區別在于,事件是異步的,而我們自己實現的這兩種模式,雖然使用了回調函數,但大都是同步的。愛掏網 - it200.com而這兩種設計模式之間的區別在于,發布訂閱模式的事件池是統一的,觀察者模式的事件池分散在各個發布者上面。愛掏網 - it200.com
原文發布時間為:2024年06月23日 原文作者:磚用冰西瓜 本文來源掘金如需轉載請聯系原作者