所有在模塊的代碼頂部聲明的常量在模塊外都是不可見的,但你可能想使一些常量可見,比如CLASS_NAMES。此時,你只需在Y.Base.create的最后一個參數中,即聲明靜態(tài)成員的區(qū)域聲明:CLASS_NAMES: CLASS_NAMES
這樣這一對象及其包含的所有屬性都可通過Y.MyWidget.CLASS_NAMES來訪問。
我建議盡可能將widget的HTML字符串都調整好再執(zhí)行Y.Node.create。因為在Javascript中,字符串操作的速度比DOM操作快很多。在Y.Node.create調用前做的越多,代碼執(zhí)行的速度就越快。
所有widget還都會用到的方法就是bindUI。你可以在這個函數創(chuàng)建元素綁定事件,例如你可以給上面TEMPLATE中的<input>綁定valueChange事件,使textbox中值和配置屬性中的對應的值始終保持一致。代碼和用戶都有可能去修改input中的值。如果是來自內部代碼的更新值,textbox要刷新以顯示新值,如果改變來自用戶輸入則不用刷新。如不這樣,就會陷入死循環(huán):textbox的value屬性發(fā)生改變,觸發(fā)change事件,響應函數又改變textbox的值,這一改變又觸發(fā)了change事件……讓我們看看如何處理這一情況。我們在input上綁定自定義的valueChange事件,當然要先在模塊的requires中加入event-valuechange模塊。 this._eventHandles.push(this._inputEl.after(‘valueChange’, this._afterInputChange, this));
我們假設_inputEl對象指向textbox。事件響應函數如下: _afterInputChange: function (ev) { this.set(VALUE, ev.target.get(VALUE),{source:UI}); },
這里假設我們事先已定義了表示value和ui的常量VALUE和UI。我們簡單的將配置屬性中的值設置為input中的值,我還給函數加了第三個參數{source:UI}。set函數可以接受第三個參數,這個參數是一個object對象,它的屬性可以加入attribute change事件的事件對象(event facade)中,由此就可以區(qū)別textbox的valueChange事件是來自內部代碼還是用戶輸入。在bindUI中,我們可能已經這樣設置了事件監(jiān)聽: this._eventHandles.push(this.after(‘valueChange’,this._afterValueChange));
這是一個監(jiān)聽value變化的事件監(jiān)聽,上一個例子也是對<input>的value的變化作監(jiān)聽。兩個事件名稱都一樣,實際上,它們都是對一個叫做value的值的變化進行監(jiān)聽,但實際卻不一樣。通常,對屬性變化的監(jiān)聽會放在initializer里,而此例涉及改變UI元素,所以把它放在bindUI中,也提醒我們這個事件響應涉及textbox。事件響應函數如下: _afterValueChange: function (ev) { if (ev.source === UI) { return; } this._inputEl.set(VALUE, ev.newVal); },
首先我們檢查事件對象的source屬性。如果事件來自UI,我們直接忽略。在這里,屬性名UI和它的值都是任意的,你可以根據自己喜好定義。我在設定value的屬性值時定義了UI和它的值,所以在這里我就可以訪問UI這一屬性,你也可以用其它的鍵值對。實際上,widget也提供了一個相同功能的常數Y.Widget.UI_SRC,只是名字有點長,所以我寧愿自己定義。
一個小技巧:你可以使用_set代替set來改變只讀屬性的值。_set方法本來是作為受保護方法,只能在類及其子類中訪問的,但是javascript中對象成員都是公有的,所以_set實際上是個公共方法,外部也能訪問。即使這樣,我們還是會給只讀屬性聲明readOnly:true,并且在API文檔里也將這一屬性標為只讀。
最后一個實例方法是syncUI。前兩個方法renderUI和bindUI會且僅會執(zhí)行一次,但syncUI則至少被widget自身調用一次,你也可以在后面的程序中多次調用這個方法。syncUI的作用是根據對象的狀態(tài)刷新其外觀。對象的狀態(tài)可能一直在變化, 界面也會跟著變化。不過,如何編寫這個方法不能一概而論,要根據具體情況。對于簡單的用戶界面,syncUI可以在每次有變化發(fā)生時都重繪界面中的全部內容。而對于復雜的用戶界面,重繪整個界面費時且會造成圖像閃爍,所以你最好只重繪發(fā)生變化的部分,這樣的話,你就需要將重繪不同部分的代碼分別放在不同的函數中,syncUI會將每一部分只調用一次。還有,在先前的renderUI的例子中,我改變了textbox的值,而只有在syncUI執(zhí)行之后,這一變化才能在屏幕上顯示出來。
更常見的使用方法是給每個UI元素設置單獨的重繪函數。這個函數會在初始化時被syncUI調用一次,之后會在配置屬性的發(fā)生變化后,通過事件響應函數調用。例如 _valueUIRefresh: function (value) { this._inputEl.set(VALUE, value); }
這一函數和其它相似功能的重繪函數會在syncUI中被調用: syncUI: function () { this._valueUIRefresh(this.get(VALUE)); // other such refreshers },
在after事件響應函數中的代碼如下: _afterValueChange: function (ev) { if (ev.source === UI) { return; } this._valueUIRefresh(ev.newVal); },
出處:Taobao.com UED Team
責任編輯:bluehearts
上一頁 使用YUI 3開發(fā)Web應用的訣竅 [5] 下一頁 使用YUI 3開發(fā)Web應用的訣竅 [7]
◎進入論壇網頁制作、WEB標準化版塊參加討論,我還想發(fā)表評論。
|