技術(shù)交流QQ群:1027579432,歡迎你的加入!
歡迎關注我的微信公眾號:CurryCoder的程序人生
1.注冊事件(綁定事件)
- 注冊事件概述:給元素添加事件,稱為注冊事件或綁定事件。
- 注冊事件有兩種方法:
- 傳統(tǒng)方式
- 方法監(jiān)聽注冊方式
-
傳統(tǒng)方式:利用on開頭的事件onclick署拟,如下例所示:
- 特點:注冊事件的唯一性;
- 同一個元素同一個事件只能設置一個處理函數(shù),最后注冊的處理函數(shù)將會覆蓋前面注冊的處理函數(shù)剩膘;
<button>傳統(tǒng)注冊事件方式</button> <button>方法監(jiān)聽注冊事件</button> <script> var btns = document.querySelectorAll('button'); btns[0].onclick = function() { alert('hi~'); } btns[0].onclick = function() { alert('hi old are you?'); } </script>
-
方法監(jiān)聽注冊方式:w3c標準推薦方式;addEventListener()它是一個方法盆顾;IE9之前的IE不支持此方法怠褐,可使用attachEvent()代替。
- 特點:同一個元素同一個事件可以注冊多個監(jiān)聽器您宪;
- 按注冊順序依次執(zhí)行奈懒。
-
addEventListener()事件監(jiān)聽方式:
eventTarget.addEventListener(type, listener[, useCapture])
- eventTarget.addEventListener()方法將指定的監(jiān)聽器注冊到eventTarget(目標對象)上,當該對象觸發(fā)指定的事件時宪巨,就會執(zhí)行事件處理函數(shù)磷杏。該方法接收三個參數(shù):
- type: 事件類型字符串,如click捏卓、mouseover极祸、注意這里不要帶on;
- listener: 事件處理函數(shù),事件發(fā)生時遥金,會調(diào)用該監(jiān)聽函數(shù)峦椰;
- useCapture: 可選參數(shù),是一個布爾值汰规,默認為false汤功,學完DOM事件流后再進一步學習。
<button>傳統(tǒng)注冊事件方式</button> <button>方法監(jiān)聽注冊事件</button> <script> // 事件監(jiān)聽方式注冊事件 btns[1].addEventListener('click', function() { alert('22'); }) btns[1].addEventListener('click', function() { alert('666'); }) </script>
- eventTarget.addEventListener()方法將指定的監(jiān)聽器注冊到eventTarget(目標對象)上,當該對象觸發(fā)指定的事件時宪巨,就會執(zhí)行事件處理函數(shù)磷杏。該方法接收三個參數(shù):
-
attachEvent()事件監(jiān)聽方式:該方法了解即可溜哮!注意:IE8及早期版本支持滔金。
eventTarget.attachEvent(eventNameWithOn, callback)
- eventTarget.attachEvent()方法將指定的監(jiān)聽器注冊到eventTarget(目標對象)上,當該對象觸發(fā)指定的事件時茂嗓,指定的回調(diào)函數(shù)就會被執(zhí)行餐茵。該方法接收兩個參數(shù):
- eventNameWithOn:事件類型字符串,如onclick述吸、onmouseover,這里要帶on忿族;
- callback:事件處理函數(shù),當目標觸發(fā)事件時回調(diào)函數(shù)被調(diào)用蝌矛;
<button>傳統(tǒng)注冊事件方式</button> <button>方法監(jiān)聽注冊事件</button> <button>IE9 attachEvent</button> <script> // attachEvent IE9以前的版本支持 btns[2].attachEvent('onclick', function(){ alert('IE9'); }) </script>
- eventTarget.attachEvent()方法將指定的監(jiān)聽器注冊到eventTarget(目標對象)上,當該對象觸發(fā)指定的事件時茂嗓,指定的回調(diào)函數(shù)就會被執(zhí)行餐茵。該方法接收兩個參數(shù):
-
注冊事件兼容性解決方案:處理兼容性的原則是先照顧大多數(shù)瀏覽器道批,再處理特殊瀏覽器。
function addEventListener(element, eventName, fn) { // 判斷當前瀏覽器是否支持addEventListener方法 if(element.addEventListener){ element.addEventListener(eventName, fn); }else if(element.attachEvent){ element.attachEvent('on' + eventName, fn); }else { // 相當于element.onclick = fn; element['on' + eventName] = fn; } }
2.刪除事件(解綁事件)
-
刪除事件的方式:
-
傳統(tǒng)注冊方式:eventTarget.onclick = null;
<div>1</div> <div>2</div> <div>3</div> <script> var divs = document.querySelectorAll('div'); divs[0].onclick = function() { alert('11'); // 傳統(tǒng)方式刪除事件 divs[0].onclick = null; } </script>
-
方法監(jiān)聽注冊方式:eventTarget.removeEventListener(type, listener[, useCapture])與eventTarget.detachEvent(eventNameWithOn, callback);
<div>1</div> <div>2</div> <div>3</div> <script> // 方法監(jiān)聽注冊方式刪除事件 divs[1].addEventListener('click', fn); // 里面的fn不需要調(diào)用加小括號 function fn() { alert('666'); divs[1].removeEventListener('click', fn); } divs[2].attachEvent('onclick', fn1); function fn1() { alert('888'); divs[2].detachEvent('onclick', fn1); } </script>
-
刪除事件兼容性解決方案:
function removeEventListener(element, eventName, fn){ // 判斷當前瀏覽器是否支持removeEventListener方法 if(element.removeEventListener){ element.removeEventListener(eventName, fn); }else if(element.detachEvent){ element.detachEvent('on' + eventName, fn); }else{ element['on' + eventName] = null; } }
-
傳統(tǒng)注冊方式:eventTarget.onclick = null;
3.DOM事件流
- 事件流描述的是從頁面中接收事件的順序入撒。
-
事件發(fā)生時會在元素節(jié)點之間按照特定的順序傳播隆豹,這個傳播過程即DOM事件流。例如茅逮,給一個div注冊了一個點擊事件:
DOM事件流.png -
DOM事件流分為三個階段:
- 1.捕獲階段(事件捕獲):網(wǎng)景最早提出璃赡,由DOM最頂層節(jié)點開始,然后逐級向下傳播到最具體的元素接收的過程献雅。
- 2.當前目標階段
- 3.冒泡階段(事件冒泡):IE最早提出碉考,事件開始時由最具體的元素接收,然后逐級向上傳播到DOM最頂層節(jié)點的過程挺身。
-
DOM事件流形象化理解:向水里扔一塊石頭侯谁,首先它會有一個下降的過程,這個過程可以理解為從最頂層向事件發(fā)生的最具體元素(目標點)的捕獲過程瞒渠;之后會產(chǎn)生泡泡良蒸,會在最低點(最具體元素)之后漂浮到水面上技扼,這個過程相當于事件冒泡伍玖。
DOM事件流.png -
注意:
- js代碼中只能執(zhí)行捕獲或者冒泡其中的一個階段;
- onclick和attachEvent只能得到冒泡階段剿吻;
- addEventListener(type, listener[, useCapture])第三個參數(shù)如果是true窍箍,表示在事件捕獲階段調(diào)用事件處理程序;如果false(默認值),表示在事件冒泡階段調(diào)用事件處理程序椰棘。
- 實際開發(fā)中我們很少使用時間捕獲纺棺,更關注事件冒泡。
- 有些事件是沒有冒泡的邪狞,如onblur祷蝌、onfocus、onmouseenter帆卓、onmouseleave等
- 事件冒泡有時候會帶來麻煩巨朦,有時候又會幫助我們很巧妙的做某些事件,后面會介紹剑令。
4.事件對象
- 官方解釋:event對象代表事件的狀態(tài)糊啡,如鍵盤按鍵的狀態(tài)、鼠標的位置吁津、鼠標按鈕的狀態(tài)等棚蓄。
- 簡單理解:事件發(fā)生后,與事件相關的一系列信息數(shù)據(jù)的集合都放到這個對象中碍脏,這個對象就是事件對象event梭依,它有很多屬性和方法。
- 比如:
- 誰綁定了這個事件典尾;
- 鼠標觸發(fā)事件的話睛挚,會得到鼠標的相關信息,如鼠標位置急黎。
- 鍵盤觸發(fā)事件的話扎狱,會得到鍵盤的相關信息,如按下了哪個鍵勃教。
<script> // 事件對象 var div = document.querySelector('div'); div.onclick = function(e) { console.log(e); // 兼容性處理方法 e = e || window.event; console.log(e); } div.addEventListener('click', function(e){ console.log(e); }) // 1.event就是一個事件對象淤击,寫到我們監(jiān)聽函數(shù)的小括號中,當形參來看 // 2.事件對象只有有了事件才會存在故源,它是系統(tǒng)給我們自動創(chuàng)建的污抬,不需要我們傳遞參數(shù) // 3.事件對象是我們事件的一系列相關數(shù)據(jù)的集合,根事件相關的绳军,比如鼠標點擊里面就包含了鼠標的相關信息印机,如鼠標坐標等信息。如果是鍵盤事件里面就包含了鍵盤事件的信息门驾,如判斷用戶按下了哪個鍵 // 4.這個事件對象我們可以自己命名射赛,如event、evt奶是、e // 5.事件對象也有兼容性問題楣责,ie8以下瀏覽器通過window.event </script>
-
事件對象的使用方法:
- 這個event是一個形參竣灌,系統(tǒng)幫我們設定為事件對象,不需要傳遞實參過去秆麸。
- 當我們注冊事件時初嘹,event對象就會被系統(tǒng)自動創(chuàng)建,并依次傳遞給事件監(jiān)聽器(事件處理函數(shù))
eventTarget.onclick = function(event){ // 這個event就是事件對象沮趣,還可以寫成evt或e } eventTarget.addEventListener('click', function(event){ // 這個event就是事件對象屯烦,還可以寫成evt或e })
-
事件對象的兼容性方案:
- 事件對象本身的獲取存在兼容性問題:
- 標準瀏覽器中是瀏覽器給方法傳遞的參數(shù),只需要定義形參e就可以獲取到房铭。
- 在IE6~8中漫贞,瀏覽器不會給方法傳遞參數(shù),如果需要的話育叁,需要到window.event中獲取查找迅脐。
- 解決方法:e = e || window.event;
- 事件對象本身的獲取存在兼容性問題:
-
事件對象的常見屬性和方法:
事件對象的常見屬性和方法.png
5.阻止事件冒泡
- 事件冒泡:開始時由最具體的元素接收,然后逐級向上傳播到DOM最頂層節(jié)點豪嗽。
- 事件冒泡本身的特性谴蔑,會帶來壞處,也會帶來好處龟梦,需要我們靈活掌握隐锭。
-
阻止事件冒泡的兩種方法:
- 標準寫法:利用事件對象中的stopPropagation()方法;具有兼容性問題计贰。
- 非標準寫法:IE6~8利用事件對象的cancelBubble屬性钦睡;
-
阻止事件冒泡的兼容性解決方案(了解):
if(e && e.stopPropagation){ e.stopPropagation(); }else{ window.event.cancelBubble = true; }
6.事件委托(代理、委派)
- 事件冒泡本身的特性躁倒,會帶來壞處荞怒,也會帶來好處,需要我們靈活掌握秧秉。(好處是類似于生活中幫別人代拿快遞)
<ul> <li>知否知否應是綠肥紅瘦</li> <li>知否知否應是綠肥紅瘦</li> <li>知否知否應是綠肥紅瘦</li> <li>知否知否應是綠肥紅瘦</li> <li>知否知否應是綠肥紅瘦</li> </ul>
- 點擊每個li都會彈出對話框褐桌,以前需要給每個li注冊事件,是非常麻煩的象迎。而且訪問DOM次數(shù)越多荧嵌,就會延長整個頁面的交互就緒時間。
- 事件委托:也稱為事件代理砾淌,在jQuery中稱為事件委派啦撮。
- 事件委托的原理:不是每個子節(jié)點單獨設置事件監(jiān)聽器,而是事件監(jiān)聽器設置在其父節(jié)點上汪厨,然后利用事件冒泡原理影響設置每個子節(jié)點赃春。
- 以上案例的解決方法:給ul注冊點擊事件,然后利用事件對象的target來找到當前點擊的li骄崩。因為點擊li聘鳞,事件會冒泡到ul上薄辅,ul有注冊事件要拂,就會觸發(fā)事件監(jiān)聽器抠璃。
- 事件委托的作用:只操作了一次DOM,提高了程序的性能脱惰。
7.常見的鼠標事件
常見的鼠標事件.png
%7CimageView2/2/w/1240)
-
禁止鼠標右鍵菜單:contextmenu主要控制應該何時顯示上下文菜單搏嗡,主要用于程序員取消默認的上下文菜單。
document.addEventListener('contextmenu', function(e){ e.preventDefault(); });
-
禁止鼠標選中(selectstart開始選中):
document.addEventListener('selectstart', function(e){ e.preventDefault(); });
- event對象代表事件的狀態(tài)拉一,根事件相關的一系列信息的集合采盒。目前,我們主要是用鼠標事件對象MouseEvent和鍵盤事件對象keyboardEvent蔚润。
-
鼠標事件對象MouseEvent
鼠標事件對象.png
8.常見的鍵盤事件
-
事件除了使用鼠標觸發(fā)磅氨,還可以使用鍵盤觸發(fā)。
常見的鍵盤事件.png -
注意:
- 如果使用addEventListener不需要加on嫡纠;
- onkeypress和前面2個的區(qū)別是烦租,它不能識別功能鍵,如左右箭頭除盏、shift叉橱、ctrl鍵;
- 三個事件的執(zhí)行順序是:keydown --> keypress --> keyup
-
鍵盤事件對象keyboardEvent
keyCode屬性.png -
注意:
- onkeydown和onkeyup不區(qū)分字母大小寫者蠕,onkeypress區(qū)分字母大小寫窃祝;
- 在實際開發(fā)中,更多使用的是keydown和keyup踱侣,它能識別所有的鍵(包括功能鍵)粪小;