更多相關內容見博客 github.com/zhuanyongxi…javascript
html標籤中的寫法html
<image id="element" src="hello.png" onclick="alert('Hi')"/>
複製代碼
在JS中的綁定方法:vue
var element = document.getElementById("element");
element.onclick = function(e) {}
複製代碼
dom0是節點元素的私有屬性。同一個事件只能綁定一個,綁定多個,只有最後一個有效。直接寫在html節點上的也會被覆蓋。以下面的代碼,最後點擊觸發的時候只會打印3。java
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
之類的事件的時候就須要注意了。git
有標準,不涉及實踐。github
addEventListener
方法在節點對象的原型鏈上。綁定實名函數更好,由於能夠移除。第三個參數用於選擇在什麼階段觸發,默認false表示在冒泡階段觸發。編程
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:api
function fn() {console.log(1)};
element.addEventListener('change', fn, false);
element.addEventListener('change', fn, false);
複製代碼
此外,addEventListener
還能夠綁定DOM0中沒有的事件,如DOMContentLoaded。瀏覽器
與DOM2的區別在於事件的種類,其餘的同樣。如keyup
、keydown
、keypress
都是DOM3的事件,click
也是DOM3級事件,具體到MDN中搜索DOM L3
。
簡要的說就是事件的三個階段:捕獲階段--目標階段--冒泡階段。詳細說就是以下圖。
當用戶點擊瀏覽器窗口,事件發生,捕獲階段開始:window--document--html--body--父節點--目標節點(目標階段),而後開始冒泡階段:目標節點--父節點--body--html--document--window。
幾個須要注意的api:
preventDefault的做用是阻止瀏覽器默認行爲,什麼是默認行爲?除了你本身綁定的操做以外的行爲都是瀏覽器的默認行爲,如a標籤的跳轉,表單的提交,鼠標右鍵呼出菜單等等。
此外event.returnValue = false;
、return false;
也能夠達到跟proventDefault
一樣的效果。若是是a標籤,阻止跳轉,能夠href="javascript:;"
或href=javascript:void 0;
stopPropagation的做用是阻止事件的傳播。阻止的是其餘節點上的事件。
stopImmediatePropagation的做用也是阻止事件的傳播。它不但能阻止其餘節點上的事件,當前節點上的其餘未觸發的事件也會一併阻止。以下代碼,只打印1:
element.addEventListener('click', function(event) {
event.stopImmdiatePropagation();
console.log(1);
}, false);
element.addEventListener('click', function() {console.log(2)}, false);
複製代碼
currentTarget,當前會執行的回調函數綁定的那個節點。
elementFirst.addEventListener('click', function(event) {
console.log(event.currentTarget); // elementFirst
}, false);
elementSecond.addEventListener('click', function(event) {
console.log(event.currentTarget); // elementSecond
}, false);
複製代碼
target,就是事件流中的目標階段的那個節點,也就是目標節點。須要注意的是,事件是否發生與是否綁定的操做沒有關係,即使沒有在一個節點上綁定事件的操做,事件依然會發生。target
能夠在事件委託中使用。
var myEvent = new Event('theEvent');
theTarget.addEventlistener('theEvent', function() {doSomething()})
theTarget.dispatchEvent(myEvent); // theTarget是一個節點,或者說是一個能夠調用addEventListener方法的對象。
複製代碼
此外customEvent
作到跟Event
一樣的效果,他們的區別在於,customEvent
能夠加一些本身須要的數據進去,不過兼容性沒有Event
好。
用Event
建立了實例以後,也能夠用myEvent.data = {}
的方式給數據,效果是同樣的。
這有什麼用?能夠用來作全局範圍內的廣播,使模塊間解耦。在vue中有一個用於組件間通信的EventBus,自定義事件就能夠用來實現這一功能。
事件委託就是把原本應該由你來作的事情,讓別人幫忙作一下。
在實際編程中,可能會出現這樣的場景,一個節點下有多個子節點,每一個子節點都要有相應的事件綁定,這個時候咱們就能夠利用事件的冒泡,把事件綁定在父節點上,而後用event.target
來區分究竟是哪一個子節點觸發的事件。當這些子節點須要動態增減的時候,使用事件委託就顯得尤其方便了,不管是寫代碼的效率仍是程序運行的效率都會更高。
侷限性:focus、blur這樣的事件沒有在冒泡機制,沒法委託。另一些消耗較高的事件如mousemove和mouseout也不適合委託。以下圖
若是咱們把B區域的mousemove事件委託到A區域,當事件在A區域發生的時候,對應的操做也會執行,若是是消耗較低的事件,就不會有太大的影響,可若是是消耗較高的事件,就會顯得有點浪費了。
這兩種設計模式與事件很是的相似。與事件的區別在於,事件是異步的,而咱們本身實現的這兩種模式,雖然使用了回調函數,但大都是同步的。而這兩種設計模式之間的區別在於,發佈訂閱模式的事件池是統一的,觀察者模式的事件池分散在各個發佈者上面。
參考文章