事件是 JavaScript 與 HTML 交互的基礎。要實現用戶與頁面的交互,先要對目標元素綁定特定的事件、設置事件處理函數,而後用戶觸發事件,事件處理函數執行,產生交互效果。
<!-- more -->
DOM 級別分爲四個級別:DOM0 級、DOM1 級、DOM2 級、DOM3 級;
<br/>
DOM 事件級別分爲三個級別:javascript
<button id="btn" type="button"></button> <script> var btn = document.getElementById('btn') btn.onclick = function() { console.log('Hello World') } // btn.onclick = null // 解綁事件 </script>
缺點:沒法設置多個事件處理函數
<button id="btn" type="button"></button> <script> var btn = document.getElementById('btn'); btn.addEventListener('click', showFn, false) btn.addEventListener('click', showFn2, false) // btn.removeEventListener('click', showFn, false) // 解綁事件 function showFn() { alert('Hello World'); } function showFn2() { alert('Hello World2'); } </script>
能夠爲事件設置多個事件處理函數,能夠經過第三個參數 ( useCapture ) 設置在什麼階段執行事件處理函數,默認是 false, 即在事件冒泡階段執行事件處理函數。
須要注意的是在 IE8 及如下版本須要用 attachEvent
和 detachEvent
實現,只有兩個參數,事件名須要以 on 開頭,只支持在事件冒泡階段執行事件處理函數。html
DOM3 級事件是在 DOM2 級事件的基礎上添加了更多的事件類型,容許自定義事件。
// 自定義事件 var event = new Event('test') // 給元素綁定事件 domElement.addEventListener('test', function() { console.log('event test') },) // 觸發事件 setTimeout(function() { domElement.dispatchEvent(event) }, 1000)
想象畫在一張紙上的一組同心圓。若是把手指放在圓心上,那麼手指指向的不單單是一個圓,而是紙上的全部圓。因此若是點擊了某個按鈕,點擊事件不單單發生在這個按鈕上,整個頁面也被點擊了。
事件流又稱爲事件傳播,描述的是從頁面中接收事件的順序。DOM2 級事件規定事件流包括三個階段: 事件捕獲(capturing phase)、目標事件(target phase)、事件冒泡(bubbling phase)。
<br/>
發生的順序是:事件捕獲階段 --> 目標事件階段 --> 事件冒泡階段 java
事件開始時由最具體的元素(目標元素)接收,而後逐級向上傳播。
<style> #parent { width: 200px; height: 200px; background-color: green; } #child { width: 100px; height: 100px; background-color: yellow; } </style> <div id="parent"> <div id="child">目標元素</div> 父級元素 </div> <script> var parent = document.getElementById('parent') var child = document.getElementById('child') parent.addEventListener('click', function(e) { console.log('parent bubbling') }, false) child.addEventListener('click', function() { console.log('target bubbling') }, false) document.body.addEventListener('click', function() { console.log('body bubbling') }, false) document.documentElement.addEventListener('click', function() { console.log('html bubbling') }, false) document.addEventListener('click', function() { console.log('document bubbling') }, false) window.addEventListener('click', function() { console.log('window bubbling') }, false) </script>
運行結果:
<br/>segmentfault
事件按 window -> document -> html -> body -> ... -> 目標元素 的方向向下層元素傳遞。
<style> #parent { width: 200px; height: 200px; background-color: green; } #child { width: 100px; height: 100px; background-color: yellow; } </style> <div id="parent"> <div id="child">目標元素</div> 父級元素 </div> <script> var parent = document.getElementById('parent') var child = document.getElementById('child') parent.addEventListener('click', function(e) { console.log('parent capture') }, true) child.addEventListener('click', function() { console.log('target capture') }, true) document.body.addEventListener('click', function() { console.log('body capture') }, true) document.documentElement.addEventListener('click', function() { console.log('html capture') }, true) document.addEventListener('click', function() { console.log('document capture') }, true) window.addEventListener('click', function() { console.log('window capture') }, true) </script>
運行結果:
<br/>
![bubbling](https://user-gold-cdn.xitu.io...
)瀏覽器
在用戶觸發事件,執行事件處理函數的時候,默認會向事件處理函數傳入一個 event 對象,它記錄了該事件的狀態和行爲。
type
事件類型target
事件發出者(觸發事件的元素)currentTarget
事件監聽者(被綁定事件的元素)dom
stopPropagation()
阻止事件冒泡或捕獲preventDefault()
阻止瀏覽器默認行爲<div id="parent"> <div id="child"></div> </div> <script> var parent = document.getElementById('parent') function handler(e) { console.log(e.target) console.log(e.currentTarget) console.log(this) } // 給父盒子註冊點擊事件 parent.addEventListener('click', handler, false) </script>
當點擊 parent 時,輸出:編輯器
1 <div id="parent">...</div> 2 <div id="parent">...</div> 3 <div id="parent">...</div>
當點擊 child 時,輸出:函數
1 <div id="child">...</div> 2 <div id="parent">...</div> 3 <div id="parent">...</div>
因此target
是事件發出者,curentTarget
是事件監聽者,事件處理函數中的this
等同於e.currentTarget
// 事件處理函數 function handleClick(event) { var e = event || window.event ··· }
··· var target = e.target || e.srcElement ···
··· e.preventDefault ? e.preventDefault() : (e.returnValue = false) ···
··· e.stopPropagation ? e.stopPropagation() : (e.cancelBubble = true) ···
function addEvent(element, type, fn) { element.addEventListener ? element.addEventListener(type, fn, false) : element.attachEvent('on'+ type, fn) } function removeEvent(element, type, fn) { element.removeEventListener ? element.removeEventListener(type, fn, false) : element.detachEvent('on'+ type, fn) }
屬性 | 描述 |
---|---|
altKey | 返回當事件被觸發時,」ALT」 是否被按下。 |
button | 返回當事件被觸發時,哪一個鼠標按鈕被點擊。 |
clientX | 返回當事件被觸發時,鼠標指針的水平座標。 |
clientY | 返回當事件被觸發時,鼠標指針的垂直座標。 |
ctrlKey | 返回當事件被觸發時,」CTRL」 鍵是否被按下。 |
metaKey | 返回當事件被觸發時,」meta」 鍵是否被按下。 |
relatedTarget | 返回與事件的目標節點相關的節點。 |
screenX | 返回當某個事件被觸發時,鼠標指針的水平座標。 |
screenY | 返回當某個事件被觸發時,鼠標指針的垂直座標。 |
shiftKey | 返回當事件被觸發時,」SHIFT」 鍵是否被按下。 |
屬性 | 描述 |
---|---|
cancelBubble | 若是事件句柄想阻止事件傳播到包容對象,必須把該屬性設爲 true。 |
fromElement | 對於 mouseover 和 mouseout 事件,fromElement 引用移出鼠標的元素。 |
keyCode | 對於 keypress 事件,該屬性聲明瞭被敲擊的鍵生成的 Unicode 字符碼。對於 keydown 和 keyup |
offsetX,offsetY | 發生事件的地點在事件源元素的座標系統中的 x 座標和 y 座標。 |
returnValue | 若是設置了該屬性,它的值比事件句柄的返回值優先級高。把這個屬性設置爲 false 能夠阻止瀏覽器默認行爲 |
srcElement | 對於生成事件的 Window 對象、Document 對象或 Element 對象的引用。 |
toElement | 對於 mouseover 和 mouseout 事件,該屬性引用移入鼠標的元素。 |
x,y | 事件發生的位置的 x 座標和 y 座標,它們相對於用CSS動態定位的最內層包容元素。 |
屬性或方法 | 描述 |
---|---|
bubbles | 返回布爾值,指示事件是不是冒泡事件類型。 |
cancelable | 返回布爾值,指示事件是否可擁可取消的默認動做。 |
currentTarget | 返回其事件監聽器觸發該事件的元素。 |
eventPhase | 返回事件傳播的當前階段。 |
target | 返回觸發此事件的元素(事件的目標節點)。 |
timeStamp | 返回事件生成的日期和時間。 |
type | 返回當前 Event 對象表示的事件的名稱。 |
initEvent() | 初始化新建立的 Event 對象的屬性。 |
preventDefault() | 通知瀏覽器不要執行與事件關聯的默認動做。 |
stopPropagation() | 再也不派發事件(經常使用於阻止事件冒泡)。 |
閱讀原文this
參考資料:spa