目錄
事件綁定
什麼是事件?
- JS 中的事件就是對用戶特定的行爲作出相應的響應的過程
- 即瀏覽器監聽到用戶某些行爲的時候,會執行對應的綁定程序
- 每個事件都應該有自己的載體
什麼是事件的綁定?
- 在 html 元素上將觸發事件的行爲和事件的相應的程序關聯起來的過程就是事件的綁定
傳統事件綁定和符合W3C標準的事件綁定有什麼區別?
1. 傳統事件綁定:
<div onclick="">123</div>
div1.onclick = function(){};
<button onmouseover=""></button>
注意:
如果給同一個元素綁定了兩次或多次相同類型的事件,那麼綁定會被覆蓋
2. 符合W3C標準的事件綁定的方式 addEventListener/attachEvent
addEventListener / removeEventListener
兼容:firefox、chrome、IE、safari、opera;不兼容IE7、IE8
let box = document.querySelector('.box') // 獲取dom元素
function fun1(){console.log('box clicked...')} // 事件函數
box.addEventListener('click',fun1) //綁定事件
box.removeEventListener('click',fun1) //移除事件
所有的DOM節點都包含這兩個方法,並且他們都接受三個參數:
- 事件類型
- 事件處理方法
- 布爾參數,默認false (true:捕獲階段調用事件處理方法;false:冒泡階段調用事件處理方法。)
注意:
- 如果給同一個元素綁定了兩次或多次相同類型的事件,綁定依次觸發
- 支持DOM事件流
- 進行事件綁定不需要
on
前綴
attachEvent / detachEvent
兼容:IE7、IE8;不兼容firefox、chrome、IE9、IE10、IE11、safari、opera
// IE只支持事件冒泡
let box = document.querySelector('.box')
function fun1(){console.log('box clicked...')}
box.attachEvent('onclick',fun1) // 綁定事件
box.detachEvent('onclick',fun1) // 移除事件
這兩個方法都接受兩個相同的參數:
- 事件處理程序名稱
- 事件處理程序方法
注意:
- 進行事件類型傳參需要帶上
on
前綴 - 這種方式只支持事件冒泡,不支持事件捕獲
事件冒泡與捕獲
事件冒泡
由點擊的div
一層一層往上觸發事件
<div id="box1">
<div id="box2">
<div id="box3">
點擊觸發事件
</div>
</div>
</div>
let box1 = document.getElementById('box1');
let box2 = document.getElementById('box2');
let box3 = document.getElementById('box3');
box1.addEventListener('click',function(){
console.log('box1');
},false);
box2.addEventListener('click',function(){
console.log('box2');
},false);
box3.addEventListener('click',function(){
console.log('box3');
},false);
// 事件冒泡輸出:
// box3
// box2
// box1
事件捕獲
與事件冒泡相反,由最外面的div
一層一層往下觸發事件
<div id="box1">
<div id="box2">
<div id="box3">
點擊觸發事件
</div>
</div>
</div>
let box1 = document.getElementById('box1');
let box2 = document.getElementById('box2');
let box3 = document.getElementById('box3');
box1.addEventListener('click',function(){
console.log('box1');
},true);
box2.addEventListener('click',function(){
console.log('box2');
},true);
box3.addEventListener('click',function(){
console.log('box3');
},true);
// 事件捕獲輸出:
// box1
// box2
// box3
如何阻止事件冒泡和默認事件?
-
防止冒泡和捕獲
w3c的方法是e.stopPropagation()
,IE則是使用e.cancelBubble = true
-
取消默認事件
w3c的方法是e.preventDefault()
,IE則是使用e.returnValue = false
事件代理(委託)
利用事件冒泡的原理,讓自己的所觸發的事件,讓他的父元素代替執行
- js中事件冒泡我們知道,子元素身上的事件會冒泡到父元素身上。
- 事件代理就是,本來加在子元素身上的事件,加在了其父級身上。
- 那就產生了問題:父級那麼多子元素,怎麼區分事件本應該是哪個子元素的?
- 答案是:
event對象
裏有記錄的“事件源”,它就是發生事件的子元素。 - 它存在兼容性問題,在老的IE下,事件源是
window.event.srcElement
,其他瀏覽器是event.target
用事件代理有什麼好處呢?
- 第一個好處是效率高,比如:不用
for循環
爲子元素添加事件了 - 第二個好處是,
js
新生成的子元素也不用新爲其添加事件了,程序邏輯上比較方便
代碼示例:
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ul = document.getElementById('ul');
ul.onmouseover = function(e){
var e = e || window.event;
var li = e.srcElement || e.target;
// toLowerCase() 轉換爲小寫
if(li.nodeName.toLowerCase() == 'li'){ // 事件源的nodeName 判斷是不是li
li.style.background = 'red';
}
}
ul.onmouseout = function(e){
var e = e || window.event;
var li = e.srcElement || e.target;
if(li.nodeName.toLowerCase() == 'li'){ // 事件源的nodeName 判斷是不是li
li.style.background = '';
}
}
效果圖: