一,關于prototype.js中發(fā)現(xiàn)的問題
跟我再深入啃啃prototype.js
中我們討論了prototype.js中得 bind/Event.observe.
charon@xxx 提到了 Event.observe(myChk, 'click',showMessage.bind(this), false);

本來做drag的例子,發(fā)現(xiàn)prototype.js的個問題。見附件? test.htm

以下貼出了代碼:
當注冊 div的mousemove事件,并且div中包括個 img元素時,如果我們的注冊函數(shù)用到prototype.js的bind函數(shù),那拖動鼠標,不會按照你的預想執(zhí)行函數(shù)。以為是 apply/call函數(shù)的問題。但在YUL中,注冊代碼和prototype.js基本類似,但代碼會正確執(zhí)行。郁悶了半天,發(fā)現(xiàn)是bind函數(shù)實現(xiàn)的 問題,與call,apply函數(shù)無關。見

var?fun=obj.move.bind(obj);?//錯誤,bind函數(shù)有問題呀
fun=function(){return?obj.move.apply(obj)};?//正確
Event.observe("dragDiv","mousemove",fun,true
);

看來prototype.js bind函數(shù)的這層包裝有問題,雖然我還不能確定問題所在,(估計是閉包引起的)。但建議大家小心了。尤其是實現(xiàn)拖拉功能時。
也就在mousemove時才遇到這個問題。

<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(
"為了測試,請用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下可以運行,為了測試
????????return?false;
????}
}
var?obj=new?DragListener();
//因為我想在方法中用obj對象的內容,所以我用prototype.js的bind方法改變方法的?”調用對象“
//
當我下壓鼠標拖動時,會出現(xiàn)異常

/*
$("dragDiv").onmousedown?=obj.down.bind(obj);
$("dragDiv").onmousemove?=?obj.move.bind(obj);??
*/

/*
$("dragDiv").onmousedown?=obj.down;//正確?但我們在方法中用this訪問到的對象是?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);?//錯誤,bind函數(shù)有問題呀
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>



二,關于拖拉代碼實現(xiàn)的建議

附件中包括我實現(xiàn)的拖拉代碼,是失敗的,我把問題想的太簡單了。現(xiàn)在總結點經(jīng)驗,與大家分享。
1 關于時間注冊方式
? (1)
$("dragDiv").onmousedown?=obj.down;典型的傳統(tǒng)事件注冊方式,缺點一個元素一個處理函數(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頁,作者說了些問題。不過prototype.js,yul都解決了這個問題。
? (3)ajax in action 中提到的 自己實現(xiàn)的類似 swing的 事件注冊機制
可能是個好的選擇。
?
2 關于時間注冊的元素
? 附件中有我簡單的例子,我以為把事件注冊到要拖動的元素上不錯,可以避免與其它事件的混亂,也好管理,可效果是很差的,當鼠標動作很快,或鼠標到達瀏覽器邊界時就不好控制了。
? 可見把事件注冊到document是個不錯的選擇,可造成編程的難度是巨大的。
? 如dojo-0.3.0 見 dojo.dnd.HtmlDragManager,
? yul中的dragdrop.js。注意,yul中,onmousedown是注冊到被拖動元素,而move,up注冊到document.
3 關于拖拉代碼的重用
? 關于層的拖動,實現(xiàn)是很簡單的,但是如果要重用,我感覺是很困難的,主要問題還是事件注冊上。dojo對事件的注冊提供好的支持,但也夠復雜的。
? dojo,yul這些層拖動對鼠標移動到瀏覽器之外好像沒有好的控制。
? http://script.aculo.us/的實現(xiàn)也比較粗糙,bug多多,尤其是有滾動條時。

感覺http://www.google.com/ig?hl=zh-CN 是最好的,不考慮”重用“,自己實現(xiàn)自己用,javascript的類庫普遍缺乏系統(tǒng)的測試,趕快成熟吧,期待dojo。


葡萄牙比賽開始了,以后有時間修改吧,湊合看吧。