jQuery 事件处理(Events)(下)
.on() .off()
從 jQuery 1.7 開始 .on() 是主要推薦使用的事件處理綁定函式,也用來取代 .bind(), .live() 和 .delegate()。
.bind() 的缺點在於 bind 是直接將事件處理函式直接綁定在選取的元素上面,所以在綁定當時,元素必須是已經存在 DOM 中的!
例如,這樣子是沒用的:
// 這時頁面上還沒有 #foo 這元素
$('#foo').bind('click', function() { alert('hi'); });
$(document.body).append('<button id="foo">hi</button>');
// 點 button 不會有 alert!
.on() 充分利用瀏覽器事件傳播 (event bubbling) 的原理和事件委任 (event delegation) 的技巧!
在 IE8 以下,像是 change 和 submit 事件是不會 bubble 的,但 jQuery 也在底層幫你處理掉這個問題了 (yay cross-browser)!
因為事件委任的技巧讓 .on() 可以用來綁定事件處理在現在已經存在或還沒存在的 DOM 元素,像是你可以綁在 $(document).on() 監聽 DOM 的所有事件。
利用 event delegation 還有一個效能上的優點,你不用在一堆元素上各別綁定事件處理 (例如綁上千個元素,效能差),你可以只綁在 document 或 container element 上面,獲得顯著的效能改善。
例如,綁一堆 click 事件處理在 #dataTable tbody 下面的一堆 tr 元素上:
$('#dataTable tbody tr').on('click', function() {
// 這裡的 this 指向 #dataTable tbody tr 這一個 DOM 元素
// 用 $() 將 this 轉成 jQuery object
console.log( $(this).text() );
});
V.S. 綁一個 click 事件處理在 #dataTable tbody 上,然後監聽從 tr bubble 上來的 click 事件:
$('#dataTable tbody').on('click', 'tr', function() {
// 這裡的 this 指向符合 selector 的 DOM 元素,也就是 tr
console.log( $(this).text() );
});
.on() 的第三個參數,可以用來傳資料進事件處理函式:
function greet(event) {
alert('Hello ' + event.data.name);
}
$('button').on('click', {
name: 'Karl'
}, greet);
$('button').on('click', {
name: 'Addy'
}, greet);
用 .off() 來移除事件處理函式,例如:
// 移除所有 p 元素的事件處理
$('p').off();
// 移除所有 p 元素的 click 事件處理
$('p').off('click');
// 移除 #foo 的 click 事件委任
$('p').off('click', '#foo');
還可以用空白隔開多個事件,同時綁定事件處理:
$('#cart').on('mouseenter mouseleave', function(event) {
$(this).toggleClass('active');
});
替事件命名 (Namespacing events)
我們雖然可以用 unbind / off 來移除事件,但是它會一次移除全部綁定的事件處理耶,何解?答案是利用 jQuery 提供的 Namespacing events!看個例子就明白它是什麼:
// 綁定事件處理函式;並幫這事件命名為 name
// 事件名稱要接在句點 . 後面
$('#foo').on('click.name', function() { alert(1); });
$('#foo').on('click.name', function() { alert(2); });
// 觸發所有名稱是 name 的事件
$('#foo').trigger('.name');
// 移除所有名稱是 name 的事件
$('#foo').off('.name');
Namespacing events 簡單的說就是幫事件取個名字 (namespace),了解吧 :)
$(document).ready(function() {})
最後,但是很重要也很常用的。jQuery 中,大部分的操作都基於 HTML DOM,所以我們必須確定頁面文件已經完全下載好才開始執行你的程式,jQuery 提供下面這個函式來處理 DOM ready 事件 (DOMContentLoaded):
$(document).ready(function() {
// 這裡放你要執行的程式碼
});
你也可以這樣寫:
$(function() {
// 這裡放你要執行的程式碼
});
jQuery 的 DOM ready event 是等 HTML DOM 準備好就可以開始執行程式,不像一般常用的 window.onload 要連圖片、外部檔案等全部都下載完畢才會觸發 onload 事件。
DOMContentLoaded & 外部樣式表的問題?
如上述,DOMContentLoaded 事件的觸發不必等到圖片檔案等下載完畢,但這裡有個問題就是,那需要等到 "外部樣式表 (External CSS Styles)" 下載完畢嗎?關於這一點,各家瀏覽器對於 DOMContentLoaded 事件的觸發也的確不一致,在 Opera 中瀏覽器不會等外部樣式表下載完即觸發 DOM ready;而 Firefox 則會等到外部 CSS 都加載完畢。因此若你有在 jQuery ready 事件中改變了元素的 CSS 屬性,對於 Opera,你修改的屬性很可能會被接著加載的外部樣式表覆蓋過去,這也就造成跨瀏覽器處理的問題。但如果你無法避免在頁面初始階段改變 CSS 屬性,這問題我們可以利用 load 事件來避開,以確定事件的觸發會在外部樣式表下載完畢之後:
$(window).load(function() {
// Run code
});
浙公网安备 33010602011771号