一,關(guān)于prototype.js中發(fā)現(xiàn)的問(wèn)題
在
跟我再深入啃啃prototype.js
中我們討論了prototype.js中得 bind/Event.observe.
Event.observe(myChk, 'click',showMessage.bind(this), false);
本來(lái)做drag的例子,發(fā)現(xiàn)prototype.js的個(gè)問(wèn)題。見
附件? test.htm
以下貼出了代碼:
當(dāng)注冊(cè) div的mousemove事件,并且div中包括個(gè)
img元素時(shí),如果我們的注冊(cè)函數(shù)用到prototype.js的bind函數(shù),那拖動(dòng)鼠標(biāo),不會(huì)按照你的預(yù)想執(zhí)行函數(shù)。以為是
apply/call函數(shù)的問(wèn)題。但在YUL中,注冊(cè)代碼和prototype.js基本類似,但代碼會(huì)正確執(zhí)行。郁悶了半天,發(fā)現(xiàn)是bind函數(shù)實(shí)現(xiàn)的
問(wèn)題,與call,apply函數(shù)無(wú)關(guān)。見
var?fun=obj.move.bind(obj);?//錯(cuò)誤,bind函數(shù)有問(wèn)題呀
fun=function(){return?obj.move.apply(obj)};?//正確
Event.observe("dragDiv","mousemove",fun,true);
看來(lái)prototype.js bind函數(shù)的這層包裝有問(wèn)題,雖然我還不能確定問(wèn)題所在,(估計(jì)是閉包引起的)。但建議大家小心了。尤其是實(shí)現(xiàn)拖拉功能時(shí)。也就在mousemove時(shí)才遇到這個(gè)問(wèn)題。<script?language=javascript?src="prototype1.3.1.js"></script>
<script?language=javascript?src="yahoo.js"></script>
<script?language=javascript?src="event.js"></script>
<body>
<div?id="dragDiv">
??<img?src="img.jpg"?style="width:280px;height:200px"></img>
</div>
<SCRIPT?LANGUAGE="JavaScript">
<!--
if(window.attachEvent){
??
}else{
?alert("為了測(cè)試,請(qǐng)用ie");
}
function?DragListener(){
????this.down=function(){
????????return?false;
????},
????this.move=function(){
????????var?x=Event.pointerX(event);
????????var?y=Event.pointerY(event);
????????window.status="x="+x+";y="+y;//僅在ie下可以運(yùn)行,為了測(cè)試
????????return?false;
????}
}
var?obj=new?DragListener();
//因?yàn)槲蚁朐诜椒ㄖ杏胦bj對(duì)象的內(nèi)容,所以我用prototype.js的bind方法改變方法的?”調(diào)用對(duì)象“
//當(dāng)我下壓鼠標(biāo)拖動(dòng)時(shí),會(huì)出現(xiàn)異常
/*
$("dragDiv").onmousedown?=obj.down.bind(obj);
$("dragDiv").onmousemove?=?obj.move.bind(obj);??
*/
/*
$("dragDiv").onmousedown?=obj.down;//正確?但我們?cè)诜椒ㄖ杏胻his訪問(wèn)到的對(duì)象是?dom
$("dragDiv").onmousemove?=?obj.move;//正確
*/
/*
$("dragDiv").onmousedown?=associateObjWithEvent(obj,'down');//正確
$("dragDiv").onmousemove?=?associateObjWithEvent(obj,'move');//正確
*/
Event.observe("dragDiv","mousedown",obj.down.bindAsEventListener(obj),true);
/*
Function.prototype.bind?=?function(object)?{
??var?__method?=?this;
??return?function()?{
????__method.apply(object,?arguments);
??}
}
*/
var?fun=obj.move.bind(obj);?//錯(cuò)誤,bind函數(shù)有問(wèn)題呀
fun=function(){return?obj.move.apply(obj)};?//正確
Event.observe("dragDiv","mousemove",fun,true);
//YAHOO.util.Event.addListener("dragDiv",?"mousedown",?obj.down,?obj,?true);//正確
//YAHOO.util.Event.addListener("dragDiv",?"mousemove",?obj.move,?obj,?true);//正確
function?associateObjWithEvent(obj,?methodName){
????return?(function(e){
????????e?=?e||window.event;
????????return?obj[methodName](e);
????});
}
//-->
</SCRIPT>
</body>
二,關(guān)于拖拉代碼實(shí)現(xiàn)的建議
附件中包括我實(shí)現(xiàn)的拖拉代碼,是失敗的,我把問(wèn)題想的太簡(jiǎn)單了。現(xiàn)在總結(jié)點(diǎn)經(jīng)驗(yàn),與大家分享。
1 關(guān)于時(shí)間注冊(cè)方式
? (1)$("dragDiv").onmousedown?=obj.down;典型的傳統(tǒng)事件注冊(cè)方式,缺點(diǎn)一個(gè)元素一個(gè)處理函數(shù),顯然不夠好
?
(2) Event.observe("dragDiv","mousemove",fun,true);
? YAHOO.util.Event.addListener("dragDiv",?"mousedown",?obj.down,?obj,?true);
? W3C事件模型,mozilla addEventListener,ie attachEvent...,在ajax in action中文版 110頁(yè),作者說(shuō)了些問(wèn)題。不過(guò)prototype.js,yul都解決了這個(gè)問(wèn)題。
? (3)ajax in action 中提到的 自己實(shí)現(xiàn)的類似 swing的 事件注冊(cè)機(jī)制可能是個(gè)好的選擇。
?
2 關(guān)于時(shí)間注冊(cè)的元素
? 附件中有我簡(jiǎn)單的例子,我以為把事件注冊(cè)到要拖動(dòng)的元素上不錯(cuò),可以避免與其它事件的混亂,也好管理,可效果是很差的,當(dāng)鼠標(biāo)動(dòng)作很快,或鼠標(biāo)到達(dá)瀏覽器邊界時(shí)就不好控制了。
? 可見把事件注冊(cè)到document是個(gè)不錯(cuò)的選擇,可造成編程的難度是巨大的。
? 如dojo-0.3.0 見 dojo.dnd.HtmlDragManager,
? yul中的dragdrop.js。注意,yul中,onmousedown是注冊(cè)到被拖動(dòng)元素,而move,up注冊(cè)到document.
3 關(guān)于拖拉代碼的重用
? 關(guān)于層的拖動(dòng),實(shí)現(xiàn)是很簡(jiǎn)單的,但是如果要重用,我感覺是很困難的,主要問(wèn)題還是事件注冊(cè)上。dojo對(duì)事件的注冊(cè)提供好的支持,但也夠復(fù)雜的。
? dojo,yul這些層拖動(dòng)對(duì)鼠標(biāo)移動(dòng)到瀏覽器之外好像沒有好的控制。
? http://script.aculo.us/的實(shí)現(xiàn)也比較粗糙,bug多多,尤其是有滾動(dòng)條時(shí)。
感覺http://www.google.com/ig?hl=zh-CN 是最好的,不考慮”重用“,自己實(shí)現(xiàn)自己用,javascript的類庫(kù)普遍缺乏系統(tǒng)的測(cè)試,趕快成熟吧,期待dojo。
葡萄牙比賽開始了,以后有時(shí)間修改吧,湊合看吧。