js是一門事件驅動的編程語言,事件一般有多種,好比說網絡事件,IO事件,定時事件,點擊事件等等。 在這裏先只關注下前端瀏覽器中的事件。前端
如同字面意思,事件就表明了一件事或一個動做,瀏覽器中的事件有哪些node
window事件 | form事件 | keyboard事件 | mouse事件 | media事件 |
---|---|---|---|---|
afterprint | onblur | onkeydown | onclick | onabort |
beforeprint | onchange | onkeypress | ondbclick | oncanplay |
onload | oncontextmenu | onkeyup | ondrag | oncanplaythrough |
onunload | onformchange | ongragend | ondurationchange | |
onbeforeunload | onforminput | ondragenter | onemptied | |
onerror | onforcus | ondragleave | onended | |
onhaschange | oninput | ondragover | onerror | |
onmessage | oninvalid | ondragstart | onloadeddata | |
onoffline | onreset | ondrop | onloadedmetadata | |
ononline | onselect | onmousedown | onloadstart | |
onpagehide | onsubmit | onmousemove | onpause | |
onpageshow | onmouseout | onplay | ||
onpopstate | onmouseover | onplaying | ||
onredo | onmouseover | onprogress | ||
onresize | onmoseup | onratechange | ||
onstorage | onmosewhell | onreadystatechange | ||
onundo | onscroll | onseeked | ||
onunload | onseeking | |||
onstalled | ||||
onsuspend | ||||
ontimeupdate | ||||
onvolumechange | ||||
onwaiting |
從上面各方各面的事件上咱們能夠看出瀏覽器衝加載到退出那一刻,無時不刻不在觸發事件,那麼事件觸發是怎樣的一個流程呢?編程
當dom節點發生了某些操做時,就會有一個事件發射出去,這個事件從window發出,不斷通過下級節點知道目標節點,這個階段稱爲捕獲階段。全部通過的節點都會觸發這個事件,捕獲階段的任務就是創建事件傳遞線路,以便後面冒泡階段順着該線路返回至window。監聽該階段的事件,能夠經過把addEventListener第三個參數設爲true瀏覽器
node.addEventListener('click', function() {}, true);
當事件傳遞到目標節點哪裏,最終會在目標節點上觸發這個事件,這個就是目標階段(事件觸發的目標老是最最底層的節點:如<p>hello <em>world</em></p>,目標節點能夠是p也能夠是em)網絡
當事件到達目標節點以後,會沿捕獲階段的路線原路返回,這個階段稱爲冒泡階段,一樣沿途全部的節點都會再次觸發該事件。dom
由事件的觸發機制咱們能夠看到,沿途全部的父節點都會被觸發兩次該事件,一次是捕獲階段,一次是冒泡階段。編程語言
node.addEventListener('click', functioon() {console.log('hello')}, true) ; //捕獲階段 node.addEventListener('click', function() {console.log('world')}, false); //冒泡階段
因此咱們能夠經過冒泡機制來監聽父節點的事件,實現監聽子節點,尤爲是當子節點很是多的時候ide
注:因爲IE瀏覽器不支持在捕獲階段監聽事件,全部一般只用冒泡階段來監聽事件。函數
事件的冒泡機制,雖然很好,但有些場合並不使用。在比較複雜的應用中,監聽比較複雜,咱們可能只但願監聽發生具體事件的節點,這個時候就要阻止冒泡spa
阻止冒泡可使用事件對象的stopPropagation方法
node.addEventListener('click', function(e) { //operations e.stopPropagation(); }, false);
在阻止冒泡時咱們使用到了事件對象,那麼事件對象是什麼? 當一個事件被觸發的時候,會建立一個事件對象,這裏麪包含了一些有用的屬性和方法,事件對象會做爲回調函數的的第一個參數(如同node回調第一個參數永遠是error同樣)
<body> <div class="one"> <div class="two"> <div class="three"> </div> </div> </div> </body> node.addEventListener('click', function(e) { console.log('事件對象', e) }, false);
事件對象的屬性和方法等(方法大部分上是對屬性的get方法)
屬性 | 描述 | 方法 | 描述 |
---|---|---|---|
altKey | addEventListener | 添加事件綁定 | |
bubbles | 是否在冒泡階段觸發 | removeEventListener | 刪除事件綁定 |
button | stopPropagation | 中止冒泡 | |
buttons | preventDefault | 禁止瀏覽器默認行爲 | |
cancelBubble | dispatchEvent | 手動觸發事件(var event=new Event('click'); element.dispatchEvent(event) ) |
|
cancelable | 是否能夠調用proventDefault來禁止 | ||
clientX | |||
clientY | |||
composed | |||
ctrlKey | |||
currentTarget | |||
defaultPrevented | 是否禁止了默認行爲 | ||
detail | |||
eventPhase | 當前事件觸發在什麼階段。none:0;捕獲:1;目標:2;冒泡:3 | ||
fromElement | |||
isTrusted | 瀏覽器觸發(用戶真實操做觸發),仍是 JavaScript 代碼觸發的 | ||
layerX | |||
layerY | |||
metaKey | |||
movementX | |||
movementY | |||
offsetX | |||
offsetY | |||
pageX | 頁面的座標 | ||
pageY | 頁面的座標 | ||
path | 事件路徑 | ||
relatedTarget | |||
returnValue | |||
screenX | |||
screenY | |||
shiftKey | |||
sourceCapabilities | |||
srcElement | ie6-8 的觸發事件的 dom 元素,非標準 | ||
target | 觸發的目標節點 | ||
timeStamp | 返回事件發生時的時間戳 | ||
toElement | |||
type | 事件類型 | ||
view | |||
which | |||
x | |||
y |
傳統的事件綁定存在兩個不足的地方:1)須要綁定不少個eventhandler 2)事件沒法綁定後加入的節點。 事件的代理或委託就是事件觸發過程當中冒泡機制和事件對象的應用,j簡單的結構以下
document.getElementById("parent-list").addEventListener("click",function(e) { // e.target是被點擊的元素! // 若是被點擊的是li元素 if(e.target && e.target.nodeName == "li") { // 找到目標,輸出ID! console.log("find"); } });