事件高級(jí)
1 綁定和解綁事件
1.1 綁定事件
給元素添加事件,稱為注冊(cè)事件或者綁定事件抄课。注冊(cè)事件有兩種方式:傳統(tǒng)方式和方法監(jiān)聽(tīng)注冊(cè)方式
(1)傳統(tǒng)注冊(cè)方式: 利用 on 開(kāi)頭的事件 onclick
特點(diǎn):注冊(cè)事件唯一性窑睁,同一個(gè)元素同一個(gè)事件只能設(shè)置一個(gè)處理函數(shù)跺讯,最后注冊(cè)的處理函數(shù)將會(huì)覆蓋前面注冊(cè)的處理函數(shù)
(2)addEventListener 方法監(jiān)聽(tīng)注冊(cè)方式: addEventListener() 方法
特點(diǎn):同一個(gè)元素同一個(gè)事件可以注冊(cè)多個(gè)監(jiān)聽(tīng)器按注冊(cè)順序依次執(zhí)行
方法和參數(shù)
eventTarget.addEventListener(type, listener, useCapture)漩绵;
- type:事件類型字符串拴泌,比如 click 魏身、mouseover 蚪腐,注意這里不要帶 on
- listener:事件處理函數(shù),事件發(fā)生時(shí),會(huì)調(diào)用該監(jiān)聽(tīng)函數(shù)
- useCapture:可選參數(shù),是一個(gè)布爾值,默認(rèn)是 false。
btn.addEventListener('click', function() {
alert('hello world');
});
1.2 解綁事件
傳統(tǒng)的監(jiān)聽(tīng)解綁用eventTarget.onclick = null;
, 方法監(jiān)聽(tīng)注冊(cè)方式用removeEventListener
eventTarget.removeEventListener(type, listener, useCapture)
<body>
<div>點(diǎn)我</div>
<div>點(diǎn)我</div>
<script>
var divList = document.getElementsByTagName('div');
divList[0].onclick = function() {
alert(111);
this.onclick = null;
}
divList[1].addEventListener('click', fun);
function fun() {
alert(222);
this.removeEventListener('click', fun);
}
</script>
</body>
1.3 DOM 事件流
事件發(fā)生時(shí)會(huì)在元素節(jié)點(diǎn)之間按照特定的順序傳播醇坝,這個(gè)傳播過(guò)程
即 DOM 事件流。
比如我們給一個(gè)div 注冊(cè)了點(diǎn)擊事件,DOM 事件流分為3個(gè)階段:
- 捕獲階段: 由 DOM 最頂層節(jié)點(diǎn)開(kāi)始,然后逐級(jí)向下傳播到到最具體的元素接收的過(guò)程
- 當(dāng)前目標(biāo)階段
- 冒泡階段 : 事件開(kāi)始時(shí)由最具體的元素接收壶唤,然后逐級(jí)向上傳播到到 DOM 最頂層節(jié)點(diǎn)的過(guò)程
注意:
- JS 代碼中只能執(zhí)行捕獲或者冒泡其中的一個(gè)階段
- onclick 和 attachEvent 只能得到冒泡階段
- addEventListener第三個(gè)參數(shù)如果是 true,表示在事件捕獲階段。用事件處理程序批幌;如果是 false(不寫默認(rèn)就是false)荧缘,表示在事件冒泡階段調(diào)用事件處理程序
- 實(shí)際開(kāi)發(fā)中我們很少使用事件捕獲,我們更關(guān)注事件冒泡
- 有些事件是沒(méi)有冒泡的拦宣,比如 onblur截粗、onfocus、onmouseenter鸵隧、onmouseleave
- 事件冒泡有時(shí)候會(huì)帶來(lái)麻煩绸罗,有時(shí)候又會(huì)幫助很巧妙的做某些事件
下面是先son后father, 因?yàn)槭敲芭莸?/p>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var son = document.querySelector('.son');
var parent = son.parentElement;
son.addEventListener('click', function() {
alert('son');
});
parent.addEventListener('click', function() {
alert('father');
});
</script>
</body>
是先f(wàn)ather后son, 因?yàn)槭敲芭莸?/p>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var son = document.querySelector('.son');
var parent = son.parentElement;
son.addEventListener('click', function() {
alert('son');
}, true);
parent.addEventListener('click', function() {
alert('father');
}, true);
</script>
</body>
2 事件對(duì)象
2.1 什么是事件對(duì)象
代碼里的event 就是事件對(duì)象,我們還喜歡的寫成 e 或者 evt
div.onclick = function(event) {
console.log(event);
}
div.addEventListener('click', function(event) {
console.log(event);
})
event 對(duì)象代表事件的狀態(tài)豆瘫,比如鍵盤按鍵的狀態(tài)珊蟀、鼠標(biāo)的位置、鼠標(biāo)按鈕的狀態(tài)
事件對(duì)象有兼容性問(wèn)題外驱,ie678通過(guò)windows.event, 兼容性寫法:e = event || windows.event
2.2 事件對(duì)象的常見(jiàn)屬性和方法
例如育灸,阻止鏈接跳轉(zhuǎn)
// 阻止默認(rèn)行為腻窒,讓鏈接不跳轉(zhuǎn),或讓提交按鈕不提交
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
// 阻止跳轉(zhuǎn)行為
e.preventDefault();
})
阻止鏈接冒泡
e.stopPropagation()
2.3 事件委托(代理磅崭、委派)
原理:不是每個(gè)子節(jié)點(diǎn)單獨(dú)設(shè)置事件監(jiān)聽(tīng)器儿子,而是事件監(jiān)聽(tīng)器設(shè)置在其父節(jié)點(diǎn)上,然后利用冒泡原理影響設(shè)置每個(gè)子節(jié)點(diǎn)
<ul>
<li>知否知否砸喻,應(yīng)是綠肥紅瘦</li>
<li>知否知否柔逼,應(yīng)是綠肥紅瘦</li>
<li>知否知否,應(yīng)是綠肥紅瘦</li>
<li>知否知否割岛,應(yīng)是綠肥紅瘦</li>
<li>知否知否卒落,應(yīng)是綠肥紅瘦</li>
</ul>
如果要點(diǎn)擊每個(gè) li 都會(huì)彈出對(duì)話框,以前需要給每個(gè) li 注冊(cè)事件蜂桶,是非常辛苦的儡毕,而且訪問(wèn) DOM 的次數(shù)越多,這就會(huì)延長(zhǎng)整個(gè)頁(yè)面的交互就緒時(shí)間扑媚。利用事件委托可以給 ul 注冊(cè)點(diǎn)擊事件腰湾,然后利用事件對(duì)象的 target
來(lái)找到當(dāng)前點(diǎn)擊的 li,因?yàn)辄c(diǎn)擊 li疆股,事件會(huì)冒泡到 ul 上费坊,ul 有注冊(cè)事件,就會(huì)觸發(fā)事件監(jiān)聽(tīng)器
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
alert('知否知否旬痹,應(yīng)是綠肥紅瘦');
e.target.style.backgroundColor = 'pink';
})
</script>
2.4 常用的鼠標(biāo)事件
2.4.1 基礎(chǔ)鼠標(biāo)事件
2.4.2 禁止鼠標(biāo)選中文字和右鍵菜單
<script>
// 禁用右鍵菜單
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
});
document.addEventListener('selectstart', function(e) {
e.preventDefault();
});
</script>
2.4.3 鼠標(biāo)事件對(duì)象
event對(duì)象代表事件的狀態(tài)附井,跟事件相關(guān)的一系列信息的集合。現(xiàn)階段主要是用鼠標(biāo)事件對(duì)象PointerEvent
和鍵盤事件對(duì)象 KeyboardEvent
两残。
2.4.3.1 e.target和this區(qū)別
e.target返回的是觸發(fā)事件的對(duì)象永毅, this返回的是綁定事件對(duì)象
<script>
// e.target返回的是觸發(fā)事件的對(duì)象, this返回的是綁定事件對(duì)象
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
console.log(e.target); // li
console.log(this); // ul
})
</script>
2.4.3.2 鼠標(biāo)事件對(duì)象屬性
2.4.3.3 跟隨鼠標(biāo)的天使
<style>
img {
position: absolute;
}
</style>
<body>
<img src="images/angel.gif">
<script>
var img = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
var x = e.pageX;
var y = e.pageY;
img.style.left = x - 50 + 'px';
img.style.top = y - 40 + 'px';
})
</script>
</body>
2.5 常用的鍵盤事件
2.5.1 常用的鍵盤事件
- keyup : 某個(gè)鍵盤彈起時(shí)
- keydown: 某個(gè)鍵盤按下時(shí)
- keypress: 非功能鍵按下時(shí)
三個(gè)鍵盤事件執(zhí)行順序是:keydown -- keypress --- keyup
<body>
<script>
document.addEventListener('keyup', function() {
console.log('鍵盤彈起');
});
document.addEventListener('keydown', function() {
console.log('鍵盤按下');
});
document.addEventListener('keypress', function() {
console.log('非功能鍵按下');
});
</script>
</body>
2.5.2 鍵盤事件對(duì)象
keyCode: 返回該鍵的ascall值
- keyup和keydown的keyCode不區(qū)分大小寫人弓,'a'和'A'都是65
- keypress的keyCode區(qū)分大小寫沼死,'a'是65, 'A'是97
- 在我們實(shí)際開(kāi)發(fā)中,我們更多的使用keydown和keyup崔赌, 它能識(shí)別所有的鍵(包括功能鍵)
2.5.3 模擬京東按鍵輸入內(nèi)容
當(dāng)按下 s 鍵意蛀, 光標(biāo)就定位到搜索框
<body>
<div class="search">
<input placeholder="打印機(jī)">
<button>搜索</button>
</div>
<script>
var input = document.querySelector('input');
document.addEventListener('keyup', function(e) {
if(e.keyCode === 83) {
input.focus();
}
})
</script>
</body>