jQuery on() 方法詳解(二)
The event handler and its environment(事件處理程式和它的環境)
handler引數必須是一個函式(或false值,見下文), 除非你傳遞一個物件給events引數。 您可以提供一個匿名處理函式給.on()呼叫,就像上面例子中的用法,或者可以宣告一個函式,然後再將該函式名作為引數:
function notify() { alert("clicked"); }
$("button").on("click", notify);
當瀏覽器觸發一個事件或其他JavaScript呼叫的jQuery的.trigger()方法,jQuery傳遞一個event object給這個處理程式,它可以用來分析和改變事件的狀態。
預設情況下,大多數事件的冒泡從最初的 event target(目標元素) 開始的,直到document 元素。每個元素都沿著DOM層級這條路,jQuery會呼叫任何匹配的已被繫結的事件處理程式。一個處理程式可以呼叫的event.stopPropagation()防止事件向上冒泡文件樹( 從而防止這些元素的處理程式執行)。任何繫結到當前元素上的其他處理程式都將執行,為了防止這種情況,可以呼叫event.stopImmediatePropagation()。(繫結在元素上的事件被呼叫的順序和它們被繫結的順序時一樣的。 )
類似地,一個處理程式可以呼叫的event.preventDefault()取消瀏覽器預設操作行為;例如,一個連結上有一個 預設的click事件。並非是所有的瀏覽器事件的預設操作,並非所有的預設操作可以被取消。
當jQuery的呼叫處理程式時,this關鍵字指向的是當前正在執行事件的元素。對於直接事件而言,this 代表繫結事件的元素。對於代理事件而言,this 則代表了與 selector 相匹配的元素。(注意,如果事件是從後代元素冒泡上來的話,那麼 this 就有可能不等於 event.target。)若要使用 jQuery 的相關方法,可以根據當前元素建立一個 jQuery 物件,即使用 $(this)。
Passing data to the handler(將資料傳遞到處理程式)
如果data引數給.on()並且不是null 或者 undefined,那麼每次觸發事件時,event.data都傳遞給處理程式。data引數可以是任何型別,但如果是字串型別時,那麼selector引數必須提供,或明確地傳遞null,這樣的 data 引數不會誤認為是選擇器。最好是使用一個物件(鍵值對) ,所以可以作為屬性傳遞多個值。
function greet(event) { alert("Hello "+event.data.name); }
$("button").on("click", { name: "Karl" }, greet);
$("button").on("click", { name: "Addy" }, greet);
除了可以向 .on() 方法傳入 data 引數外,還可以向 .trigger() 或 .triggerHandler() 中傳入該引數。
Event performance(事件效能)
在大多數情況下,一個事件如click很少發生,效能表現並不顯注。但是,高頻率事件比如mousemove 或者 scroll可以每秒觸發幾十個次,在這種情況下明智地使用事件變得更加重要。可以按如下的辦法提高事件的效能:減少事件處理函式中的工作量;對於在事件處理函式中要用到的資訊做好快取而不是再重新計算一次;或使用setTimeout限制的頁面更新的實際次數。
許多委派的事件處理程式繫結到 document 樹的頂層附近,可以降低效能。每次發生事件時,jQuery 需要比較從 event target(目標元素) 開始到文件頂部的路徑中每一個元素上所有該型別的事件。為了獲得更好的效能,在繫結代理事件時,繫結的元素最好儘可能的靠近目標元素。避免在大型文件中,過多的在 document 或 document.body 上新增代理事件。
jQuery可以非常迅速處理tag#id.class形式的簡單選擇器,當它們是用來過濾委派事件。所以”#myForm”, “a.external”, 和 “button” 都是快速選擇器。若代理事件的選擇器使用了過於複雜的形式,特別是使用了分層選擇器的情況,雖然說這樣做會大大的降低效能,但是對於大多數應用而言,它的速度依然是足夠快的。通過為尋找更合適的元素繫結事件的方法,就可以很簡單的避免使用分層選擇器的情況。例如,使用("#commentForm").on("click", ".addNew", addComment)而不是(“body”).on(“click”, “#commentForm .addNew”, addComment)。
Additional notes(其他注意事項)
W3C指定明確指定focus 和 blur事件沒有冒泡,但是jQuery定義的跨瀏覽器的focusin 和 focusout事件,並且可以冒泡。當focus 和 blur繫結委派的事件處理程式時,jQuery分析名稱,並提供將他們分別交付給focusin 和 focusout。為了保持一致性和清晰度,使用冒泡事件型別的名稱。
在所有的瀏覽器,load ,scroll, 和 error 事件(例如, 在一個 元素上)不會冒泡。在Internet Explorer 8和更低,paste 和 reset事件不會冒泡,這樣的事件是不支援委派使用,但若事件處理函式是直接繫結在產生事件的元素上的話,是可以使用這些事件的。
window物件上的error 事件使用非標準的引數和返回值約定,所以jQuery 不支援該事件。作為替代,直接用window.onerror屬性分配一個處理函式。
例子:
Example:當點選段落時,顯示該段落中的文字:
$("p").on("click", function(){
alert( $(this).text() );
});
Example:向事件處理函式中傳入資料,並且在事件處理函式中通過名字來獲取傳入的資料:
function myHandler(event) {
alert(event.data.foo);
}
$("p").on("click", {foo: "bar"}, myHandler)
Example:取消表單的提交動作,並且通過返回 false 的方法來防止事件冒泡:
$("form").on("submit", false)
Example:通過使用 .preventDefault(),僅取消預設的動作。
$("form").on("submit", function(event) {
event.preventDefault();
});
Example: 通過使用 .stopPropagation(),防止提交事件的冒泡行為,但是並不禁止提交行為。
$("form").on("submit", function(event) {
event.stopPropagation();
});
Example:新增並觸發自定義事件(非瀏覽器事件)。
<!DOCTYPE html>
<html>
<head>
<style>
p { color:red; }
span { color:blue; }
</style>
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
<p>Has an attached custom event.</p>
<button>Trigger custom event</button>
<span style="display:none;"></span>
<script>
$("p").on("myCustomEvent", function(e, myName, myValue){
$(this).text(myName + ", hi there!");
$("span").stop().css("opacity", 1)
.text("myName = " + myName)
.fadeIn(30).fadeOut(1000);
});
$("button").click(function () {
$("p").trigger("myCustomEvent", [ "John" ]);
});
</script>
</body>
</html>
Example: 使用 物件 同時新增多個事件處理函式。
<!DOCTYPE html>
<html>
<head>
<style>
.test { color: #000; padding: .5em; border: 1px solid #444; }
.active { color: #900;}
.inside { background-color: aqua; }
</style>
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
<div class="test">test div</div>
<script>$("div.test").on({
click: function(){
$(this).toggleClass("active");
},
mouseenter: function(){
$(this).addClass("inside");
},
mouseleave: function(){
$(this).removeClass("inside");
}
});</script>
</body>
</html>