javascript
javascript事件机制与jQuery.bind的补充说明
在之前的文章javascript 事件機制 與 jQuery.Bind中,為了說明冒泡階段中Event Handler Function的表現(xiàn),我使用了event.data來記錄觸發(fā)function的次數(shù)。并且提出了一個問題,就是在jQuery.bind方式中,event.data無法正確記錄觸發(fā)的次數(shù)。后來經(jīng)過測試和查閱網(wǎng)上的相關(guān)的資料,得出了一個結(jié)論,就是我之前關(guān)于event.data的使用方式是錯誤的,或者說對于跨瀏覽器的支持是困難的。同時我也意識到,由于event.data在w3c dom level 2文檔中,并不是作為event的標(biāo)準(zhǔn)屬性出現(xiàn)的,所以jQuery對event進行了fix,使其能夠兼容各個瀏覽器。
在我糾正誤用event.data的方式之前,再描述一下我對event的理解。在我查看jQuery(1.3.2)源代碼的時候,jQuery.event的add方法中有如下代碼
// Init the element's event structure
var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
??? handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function() {
???????? // Handle the second event of a trigger and when
???????? // an event is called after a page has unloaded
???????? return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
??????????????? jQuery.event.handle.apply(arguments.callee.elem, arguments) :
??????????????? undefined;
??????? });其中的jQuery.event.handle中進行event的fix
event = arguments[0] = jQuery.event.fix(event || window.event);這里按照網(wǎng)上的資料大多是說ie下使用window.event,而firefox下使用arguments[0]也就是傳遞過來的函數(shù)參數(shù)event。可我在測試中發(fā)現(xiàn)ie6,ie7(未測試),ie8在fix之前event并不為空,也就是說在fix的時候并沒有使用window.event。
看一下這段代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
???? "">
<html xmlns="" lang="zh-CN">
<head>???
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"??? />
<title></title>
<style>
???? #panelGrandPa,#panelPaPa,#panelSon? { border:1px? solid #320213;}
?</style>
</head>
?<body>
<div id="panelGrandPa" style="width:300px;height:200px;" >
?????? <div id="panelPaPa" style="width:200px;height:100px;" >
??????????? <div id="panelSon" style="width:100px;height:50px;" >
???????????????????
??????????? </div>
?????? </div>
</div>
<script>
??? function click() {
??????? alert(event.srcElement.id);
??????? event.data = event.data || 1;
??????? alert("click function has fired? " + event.data + " times");
??????? event.data = parseInt(event.data) + 1;
??? }
??? function clickSon() {
??????? alert("I am son");
??????? click();
??? }
??? function clickGrandPa() {
??????? alert("I am GrandPa");
??????? click();
??? }
??? document.getElementById("panelGrandPa").onclick = clickGrandPa;
??? document.getElementById("panelSon").onclick = clickSon;
</script>
</body>
</html>
只能在ie8下正常工作,在ie6和ie7下都報event.data undefined錯誤。當(dāng)然我們這里使用的是window.event也就是頁面維護的event相當(dāng)于全局變量,那我們再試一下事件方法的event參數(shù)(之前閱讀jQuery源代碼提到的ie中除卻window.event另外的event)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
???? "">
<html xmlns="" lang="zh-CN">
<head>???
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"??? />
<title></title>
<style>
???? #panelGrandPa,#panelPaPa,#panelSon? { border:1px? solid #320213;}
?</style>
</head>
?<body>
<div id="panelGrandPa" style="width:300px;height:200px;" >
?????? <div id="panelPaPa" style="width:200px;height:100px;" >
??????????? <div id="panelSon" style="width:100px;height:50px;" >
???????????????????
??????????? </div>
?????? </div>
</div>
<script>
??? function click(e) {
??????? alert(event.srcElement.id);
??????? e.data = e.data || 1;
??????? alert("click function has fired? " + e.data + " times");
??????? e.data = parseInt(e.data) + 1;
??? }
??? function clickSon() {
??????? alert("I am son");
??????? click(arguments[0]);
??? }
??? function clickGrandPa() {
??????? alert("I am GrandPa");
??????? click(arguments[0]);
??? }
??? document.getElementById("panelGrandPa").attachEvent("onclick", clickGrandPa);
??? document.getElementById("panelSon").attachEvent("onclick", clickSon);
</script>
</body>
</html>
注意必須用attachEvent我們才能得到區(qū)別于window.event的“另一個”event。以上代碼在ie8下正常工作,在ie6和ie7下event.data始終為1
對于window.event,在ie6和ie7下,通過調(diào)試工具發(fā)現(xiàn)其中并沒有event.data的屬性。而attachEvent的得到的event.data 在ie6和ie7下不能正確計數(shù),始終為1,但ie8下正確。
鑒于event在各瀏覽器下的差異以及我們對書寫跨瀏覽器腳本的良好愿望,我個人認為不應(yīng)該在多個事件方法中傳遞event.data。
當(dāng)然jQuery在這方面做得更好經(jīng)過fix后的event 使得event.data在各種瀏覽器下表現(xiàn)一致
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
???? "">
<html xmlns="" lang="zh-CN">
<head>???
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"??? />
?<script type="text/javascript" src=""></script>
<title></title>
<style>
???? #panelGrandPa,#panelPaPa,#panelSon? { border:1px? solid #320213;}
?</style>
<head>
<body>
<div id="panelGrandPa" style="width:300px;height:200px;" >
?????? <div id="panelPaPa" style="width:200px;height:100px;" >
??????????? <div id="panelSon" style="width:100px;height:50px;" >
???????????????????
??????????? </div>
?????? </div>
</div>
<script>
??? function click(e) {
??????? alert(e.target.id);
??????? e.data = e.data || 1;
??????? alert("click function has fired? " + e.data + " times");
??????? e.data = parseInt(e.data) + 1;
??? }
??? function clickSon(e) {
??????? alert("I am son");
??????? click(e);
??? }
??? function clickGrandPa(e) {
??????? alert("I am GrandPa");
??????? click(e);
??? }
??? $("#panelGrandPa").bind("click", clickGrandPa);
??? $("#panelSon").bind("click", clickSon);
</script>
</body>
</html>
上述代碼在任何瀏覽器下都不能正常計數(shù),顯示event.data為1(這下ie8也不行了)。
我們分析一下原因,這也是我對上一篇提出問題的一個回答
jQuery.event.add方法封裝了attachEvent/addEventListener并且給每一個handler方法附加了data
add:function(elem, types, handler, data) {
??? //省略部分代碼
??? // if data is passed, bind to handler
??? if (data !== undefined) {
??????? // Create temporary function pointer to original handler
??????? var fn = handler;
??????? // Create unique handler function, wrapped around original handler
??????? handler = this.proxy(fn);
??????? // Store data in unique handler
??????? handler.data = data;
??? }
??? //省略部分代碼
}
在jQuery.event的fix方法中,我們看到其將傳入的event復(fù)制了一份(包括data),注意不是引用(這意味著每次方法的event都是不同的)
fix: function(event) {
??? if (event[expando])
??????? return event;
??? // store a copy of the original event object
??? // and "clone" to set read-only properties
??? var originalEvent = event;
??? event = jQuery.Event(originalEvent);
??? for (var i = this.props.length, prop; i; ) {
??????? prop = this.props[--i];
??????? event[prop] = originalEvent[prop];
??? }
??? //以下省略
}那么這樣一來,我們肯定不能在多個事件方法中用上述方法傳遞data了。
總結(jié)
以上是生活随笔為你收集整理的javascript事件机制与jQuery.bind的补充说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大话数据结构:线性表(3)
- 下一篇: 昨天飞鸽传书可能是因为太累了