詳解jQuery事件
事件是 Web 應(yīng)用中不可或缺的一個(gè)東西,用戶在應(yīng)用中執(zhí)行一個(gè)操作的時(shí)候,比如鼠標(biāo)單擊時(shí)要觸發(fā)執(zhí)行一些事情,就可以給該事件綁定一個(gè)事件處理程序(event handler)。使用 jQuery 的 .on() 方法可以為選中的元素綁定任意的 DOM 事件,并添加事件處理程序。假設(shè)有如下 HTML 結(jié)構(gòu):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> </head> <body> <button id="example" type="button">Click me!</button> <script src="http://code.jquery.com/jquery-1.11.2.js"></script> <script> // code here </script> </body> </html>
在 <script> 元素內(nèi)添加如下代碼,其中,事件名稱是 .on() 方法的第一個(gè)參數(shù),事件處理程序的回調(diào)函數(shù)作為第二個(gè)參數(shù):
$('#example').on('click', function(e) { alert('Clicked!'); });
這樣當(dāng)該按鈕元素觸發(fā)鼠標(biāo)單擊(click)事件的時(shí)候就會(huì)執(zhí)行綁定的事件處理程序,彈出一個(gè)對(duì)話框!回調(diào)函數(shù)的第一個(gè)參數(shù) e 為事件對(duì)象,通過(guò)該對(duì)象可以得到很多事件相關(guān)的信息,比如事件類型,事件發(fā)生的坐標(biāo)點(diǎn)等以及一些事件方法?;卣{(diào)函數(shù)除了可以像這樣使用一個(gè)匿名函數(shù),也可以使用一個(gè)變量標(biāo)識(shí)的函數(shù)引用:
$('#example').on('click', clickHandler);
同時(shí)綁定多個(gè)事件
另外,jQuery 還支持使用空格分隔多個(gè)事件名稱來(lái)同時(shí)綁定多個(gè)事件,比如 mouseenter mouseleave,同時(shí)給元素綁定鼠標(biāo)移入和鼠標(biāo)移出事件。可以通過(guò)事件對(duì)象的 type 屬性來(lái)判斷發(fā)生的是哪個(gè)事件:
$('#example').on('mouseenter mouseleave', function(e) { if (e.type === 'mouseenter') { // mouseenter } else { // mouseleave } });
除了上面這種方法外,還可以傳入一個(gè)鍵值對(duì)來(lái)綁定多個(gè)事件:
$('#example').on({ mouseleave: function() { // mouseleave }, mouseenter: function() { // mouseenter } });
事件上下文
同時(shí)給多個(gè)元素綁定事件處理程序的時(shí)候可以使用事件執(zhí)行的上下文來(lái)簡(jiǎn)化代碼:
$('li').on('click', function() { var $this = $(this); $this.addClass('active'); });
上下文關(guān)鍵字 this 引用的是原生 DOM 元素,所以如果要使用 jQuery 的方法需要先包裝成 jQuery 對(duì)象。
事件委托
事件會(huì)經(jīng)過(guò)一個(gè)捕捉和冒泡的過(guò)程,為了兼容,jQuery 只使用了事件的冒泡,即目標(biāo)元素觸發(fā)事件后會(huì)逐級(jí)冒泡直到頂級(jí)元素節(jié)點(diǎn)。利用事件的冒泡可以將目標(biāo)元素的事件處理程序綁定到其祖先元素上統(tǒng)一處理,可以給 .on() 方法傳入一個(gè)可選的選擇器字符串作為第二個(gè)參數(shù):
$(document).on('click', '#example', clickHandler);
此時(shí)表示將 id="example" 的元素的鼠標(biāo)單擊事件委托綁定到了 document 元素上,當(dāng)目標(biāo)元素(即 id="example" 的元素)觸發(fā)鼠標(biāo)單擊事件的時(shí)候,該事件就會(huì)冒泡到 document 元素上,從而觸發(fā)事件處理程序。使用事件委托的好處是如果頁(yè)面上有很多列表,每個(gè)列表都去綁定一個(gè)鼠標(biāo)單擊事件,那么就會(huì)有很多事件處理程序,會(huì)對(duì)性能造成影響。利用事件冒泡的原則,將事件處理程序綁定到目標(biāo)元素的父元素或者祖先元素上,可以明顯地減少事件處理程序的數(shù)量,改善性能:
$('ul').on('click', 'li', clickHandler);
使用事件委托另外一個(gè)好處是那些動(dòng)態(tài)添加的 <li> 元素也會(huì)具有事件處理程序。個(gè)人比較侵向于將事件都委托到 document 元素上方便管理,而且也不用等到 DOM 準(zhǔn)備就緒:
$(document) .on('click', 'selector-1', clickHandler) .on('focusin', 'selector-2', focusHandler);
在 IE8 中一些事件比如 submit 或者 change 是不會(huì)冒泡的,但是 jQuery 對(duì)此做了處理,因此也可以放心使用。像 focus 和 blur 事件則推薦使用相應(yīng)的 focusin 和 focusout 事件來(lái)代替。對(duì)于 mouseover 和 mouseout 事件,為了避免事件冒泡造成的不良影響,推薦使用 mouseenter 和 mouseleave 來(lái)代替。
阻止事件冒泡與默認(rèn)行為
調(diào)用事件對(duì)象的 .stopPropagation() 方法可以阻止事件冒泡:
$('#example').on('click', function(e) { e.stopPropagation(); });
這樣當(dāng)單擊事件在該元素上發(fā)生的時(shí)候就不會(huì)冒泡了。jQuery 還有另外一個(gè)方法 .stopImmediatePropagation() 調(diào)用后事件冒泡被阻止同時(shí)該元素上后面綁定的事件處理程序也不會(huì)執(zhí)行了:
$('#example').on('click', function() { alert('Clicked-1!'); // 會(huì)執(zhí)行 }).on('click', function(e) { e.stopImmediatePropagation(); }).on('click', function() { alert('Clicked-2!'); // 不會(huì)執(zhí)行 });
調(diào)用事件對(duì)象的 .preventDefault() 方法可以阻止事件的默認(rèn)行為:
$('#example').on('click', function(e) { e.preventDefault(); });
在事件處理程序中直接返回 false 可以同時(shí)取消冒泡和阻止默認(rèn)行為:
$('#example').on('click', function() { return false; });
相當(dāng)于同時(shí)調(diào)用了事件對(duì)象上面的 .stopPropagation() 和 .preventDefault() 方法。如果沒(méi)有其它操作,還可以進(jìn)一步簡(jiǎn)寫(xiě)為 $('#example').on('click', false);。
應(yīng)用示例,點(diǎn)擊按鈕顯示彈出層,點(diǎn)擊文檔其它地方隱藏:
$(document) .on('click', '#example', popup.show) .on('click', popup.hide);
由于事件冒泡,所以該彈出層并不會(huì)顯示出來(lái),需要在事件處理程序中阻止事件冒泡:
$(document) .on('click', '#example', function(e) { e.stopPropagation(); popup.show(); }).on('click', popup.hide);
獲取原生事件對(duì)象
事件處理程序中引用的事件對(duì)象實(shí)際上是經(jīng)過(guò) jQuery 包裝過(guò)的,有時(shí)候需要使用瀏覽器原生的事件對(duì)象,要得到瀏覽器原生的事件對(duì)象可以通過(guò)事件對(duì)象的 originalEvent 屬性獲取。例如,使用拖拽事件的時(shí)候就會(huì)用到原生的事件對(duì)象:
$('#example').on('dragstart', function(e) { var originalEvent = e.originalEvent; originalEvent.dataTransfer.effectAllowed = 'move'; originalEvent.dataTransfer.setData('text/plain', $(this).text()); originalEvent.dataTransfer.setData('text/html', $(this).html()); originalEvent.dataTransfer.setDragImage('/images/drag.png', -10, -10); });
傳遞數(shù)據(jù)
可以給事件處理程序傳入數(shù)據(jù),該數(shù)據(jù)保存在事件對(duì)象的 data 屬性中:
$('#example').on('click', 1, function(e) { console.log(e.data); // 1 });
為了區(qū)別事件代理,傳遞的數(shù)據(jù)貌似不能是一個(gè)直接的字符串,不過(guò)可以傳入一個(gè)對(duì)象來(lái)代替:
$('#example').on('click', {str: 'xxx'}, function(e) { console.log(e.data.str); // xxx });
自定義事件
除了瀏覽器的標(biāo)準(zhǔn)事件,還可以綁定自定義事件的事件處理程序,其中事件名可以使用任意命名:
$('#example').on('sleep', function() { alert('Sleeping!'); });
標(biāo)準(zhǔn)事件的事件處理程序可以通過(guò)瀏覽器原生事件去觸發(fā),而自定義事件的事件處理程序則可以使用 jQuery 的 .trigger() 方法觸發(fā),使用方式如下,傳入需要觸發(fā)的事件名稱作為參數(shù):
$('#example').trigger('sleep');
可以通過(guò)給 trigger() 方法傳入更多參數(shù)來(lái)給事件處理程序傳遞數(shù)據(jù),數(shù)據(jù)會(huì)作為回調(diào)函數(shù)的參數(shù)進(jìn)行傳遞:
$('#example').on('sleep', function(e, time) { alert('Sleep at' + time); }); $('#example').trigger('sleep', '22:00');
應(yīng)用示例,使用自定義事件編寫(xiě)異步代碼:
$('#example').on('done', doHandler); function foo() { setTimeout(function() { // foo 函數(shù)的邏輯比較耗時(shí),所以使用 setTimeout 函數(shù)排隊(duì) $('#example').trigger('done'); // 執(zhí)行完了,通知一聲 }, 1000); }
foo 函數(shù)執(zhí)行完成后,就會(huì)觸發(fā)元素的 done 事件,前面綁定的 doHandler 函數(shù)就會(huì)開(kāi)始執(zhí)行。
事件命名空間
無(wú)論是瀏覽器標(biāo)準(zhǔn)事件或是自定義事件都可以添加命名空間,添加在事件名稱后面,通過(guò)一個(gè) . 號(hào)分隔,像這樣 click.widget,也可以給一個(gè)事件添加多個(gè)命名空間 click.widget.common,使用命名空間可以更有針對(duì)性地觸發(fā)或者移除某個(gè)特定的事件處理程序。比如一個(gè)元素同時(shí)綁定了 click.tab 和 click.collapse 兩個(gè)點(diǎn)擊事件,當(dāng)使用 .trigger() 方法觸發(fā) click.collapse 事件時(shí)會(huì)執(zhí)行該事件的事件處理程序,而 click.tab 的事件處理程序則不會(huì)執(zhí)行。
移除綁定事件
使用 .off() 方法可以移除綁定的事件處理程序,有下面幾種情況:
- 不指定任何參數(shù),移除該元素上綁定的所有事件處理程序。
- 指定事件名,如 .off('click') 表示移除該元素上綁定的所有單擊事件處理程序。
- 指定事件處理程序,如 .off('click', clickHandler) 表示僅移除該事件處理程序(是的,匿名函數(shù)不能這樣移除)。
- 指定事件命名空間,如 .off('.widget') 表示移除該命名空間下所有的事件處理程序(比如綁定的 click.widget 和 change.widget 事件處理程序都會(huì)被移除),該方式可以用于移除某個(gè)組件綁定的各種事件。
- 指定事件代理的元素,如 $(document).off('click', '#example'),可以移除為該元素綁定的事件代理處理程序。
一次性事件
使用 .one() 方法綁定的事件處理程序只會(huì)觸發(fā)執(zhí)行一次,一次后自動(dòng)移除:
$('#example').one('click', clickHandler);
事件節(jié)流
瀏覽器中有幾個(gè)事件會(huì)頻繁觸發(fā),比如 scroll, resize, mousemove 等,那么給這些事件綁定的事件處理程序也會(huì)跟著頻繁地執(zhí)行,導(dǎo)致頁(yè)面反應(yīng)遲鈍,要解決這個(gè)問(wèn)題,需要節(jié)流事件,減少事件處理程序執(zhí)行的頻率:
var timer = 0; // 使用一個(gè)定時(shí)器 $(window).on('scroll', function() { if (!timer) { timer = setTimeout(function() { // Do something timer = 0; }, 200); } });
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
JavaScript中的object轉(zhuǎn)換成number或string規(guī)則介紹
這篇文章主要介紹了JavaScript中的object轉(zhuǎn)換成number或string規(guī)則介紹,本文講解了object自動(dòng)轉(zhuǎn)換成string的規(guī)則、object自動(dòng)轉(zhuǎn)換成number的規(guī)則等內(nèi)容,需要的朋友可以參考下2014-12-12JavaScript中合并Object的三種基本方法小結(jié)
在開(kāi)發(fā)過(guò)程中,我們經(jīng)常會(huì)遇到合并對(duì)象的需求,今天我們就來(lái)了解一下合并對(duì)象的幾種基本方法,文中通過(guò)代碼示例介紹的非常詳細(xì),感興趣的小伙伴跟著小編一起來(lái)看看吧2023-08-08JS實(shí)現(xiàn)加載和讀取XML文件的方法詳解
這篇文章主要介紹了JS實(shí)現(xiàn)加載和讀取XML文件的方法,結(jié)合實(shí)例形式分析了javascript針對(duì)xml文件的加載與讀取相關(guān)實(shí)現(xiàn)步驟與操作技巧,需要的朋友可以參考下2017-04-04JavaScript保留兩位小數(shù)的2個(gè)自定義函數(shù)
這篇文章主要介紹了JavaScript保留兩位小數(shù)的2個(gè)自定義函數(shù),需要的朋友可以參考下2014-05-05利用 JavaScript 實(shí)現(xiàn)并發(fā)控制的示例代碼
這篇文章主要介紹了利用 JavaScript 實(shí)現(xiàn)并發(fā)控制的示例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常想詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12兼容IE,firefox的獲取節(jié)點(diǎn)的文本值的javascript代碼
javascript獲取節(jié)點(diǎn)的文本值,已經(jīng)考慮了兼容性。大家可以放心使用。注意了這里的兼容沒(méi)有使用innerText,如果要使用兼容innerText,請(qǐng)參考腳本之家以前發(fā)布的文章。2009-12-12javascript中call,apply,callee,caller用法實(shí)例分析
這篇文章主要介紹了javascript中call,apply,callee,caller用法,結(jié)合實(shí)例形式分析了javascript中call,apply,callee,caller功能、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-07-07