2012
Dec
23

YUI Widget 是一個包含 html+css+js 三個部分組成的小工具,咦

這好像是廢話,網頁的制作,本來就是這三個基本語言組成,似乎 YUI 又多過了一手,

建立 html

前面有提到 Widget 組成的元素有三個,現在就先建立其中的一項 HTML。

我要制作一個命名為 sample 的 widget ,其中 widget 包含了 headerbodyfooter 三個區塊,這個 html 將會是 YUI Widget 未來要操作的 html node ,之後所有 widget 的 event 也都會在這些 node 裡發生。

YUI Widget html
  1. <div id="sample" >
  2. <div class="hd">sample Header</div>
  3. <div class="bd">
  4. <h5>sample body</h5>
  5. <a href="#" class="hideBtn">hide me!</a>
  6. </div>
  7. <div class="ft">sample Footer</div>
  8. </div>

建立 css

widget 的第二個部分就是 css , YUI widget 對 UI 的顯示上,都是藉由 css style 來控制,除了會動態修改 style 之外, Widget 還會增加、修改 css className ,所以我們必須事先設定好 css style ,這裡先介紹一個 Widget 常見的 class: hidden , hidden 的意思就是希望 html node 可以消失,不出現在螢幕上,所以我對這個 className 下 style :display:none;。

YUI Widget css
  1. .yui3-sample-hidden {
  2. display:none;
  3. }

當你使用 YUI3 Widget 內建的 method:hide,這時 JS 就會自動對 Widget 加上 yui3-{name}-hidden 這個 className ,所以我們得先對這個 className 定義好正確的 style。

因為 sample 是我建立 widget 的名稱,所以 YUI 自動産生的 className 會以 yui3-sample 為開頭。

建立 javascript widget

有了 HTML 、css 這兩份資料之後,我們就可以開始寫 Widget js 的部分囉,這裡我宣告一個 Y.sample 的物件,並繼承 Widget 的所有 methodattribute, 另外我增加了一個 method: initializer ,當我 new sample widget 時,Widget 會自動對 .hideBtn 綁定 click 事件 ( 7 ~ 9 行)。

sampleWidget.js
  1. YUI.add("sample", function(Y){
  2. var method = {};
  3. var sample={};
  4. sample.NAME = "sample";
  5. sample.ATTRS = {}
  6. method.initializer = function() {
  7. Y.one("#sample .hideBtn").on('click', this.hide, this);
  8. }
  9.  
  10. Y.sample = Y.Base.create("sample", Y.Widget, [], method, sample);
  11. delete method,sample;
  12. },'', {requires:["base","widget"]});

有了以上三個部分,這樣就算完成了一個簡單的 Widget 了,這個 widget 會産生一個按鈕,而在點了按鈕之後,widget 將會被隱藏。

使用 widget & Demo

接下來要開始使用剛剛寫好的 Widget , 我們只要 new sample ,然後傳入 srcNode 這個參數即可, srcNode 是指 widget js 要與 html 連結的 id , 我在一開始就已經在 html 中定義 id="sample" ,所以 用 #sample ,代表 widget 會去連結 sample 這個 html node。

widget.html
  1. <script>
  2. YUI().use("node","sample",function(Y){
  3. var s = new Y.sample({
  4. srcNode: "#sample",
  5. });
  6. s.render();
  7.  
  8. })
  9. </script>
View Demo

render

YUI Widget 一開始都必須執行 render 這個 function, render 的主要功能,是為了幫 html 補上一些基本的 className ,這樣才方便 YUI 的操作,render 前要先設定 attribute srcNode (source node),這個 srcNode 要給他一個獨立的 id ,如 #widget,執行 render 後,YUI 會自動去找出 srcNode 指定的 html tag,並給 html tag 預設的 className, event。

執行 render 前的 html

這裡我建立一個簡單的 html tag ,命名為 sample ,並分成三個區塊,分別是 head, body, foot。

Widget 預設 Method

YUI Widget 預設已經宣告了一些 Method ,並定義執行的時間點。

init Method

  • new Widget Object 時,會自動執行 initializer。
  • YUI 會自動 register 一個 Object ,並記錄在 YUI 自定的 Array 裡,並且 YUI 會自動産生一個 unique id 存在 _instances 的變數中。
  • 執行 parse html , YUI 為了能夠新增 className Before Widget Render
Widget Header
Widget Body
Widget Footer
#

執行 render 後的 html

After YUI Widget Render
  1. <div id="yui_3_7_2_1_1358786231445_13" class="yui3-widget yui3-sample" style="height: 50px;">
  2. <div id="sample" class="yui3-sample-content yui3-widget-content-expanded">
  3. <div class="hd">Widget Header</div>
  4. <div class="bd">Widget Body</div>
  5. <div class="ft">Widget Footer</div>
  6. </div>
  7. </div>

從html 的變化中,可以知道,YUI 替我建立的 html 最外層加上一個 bunding box ,並自動産生一個 id = yui_3_7_2_1_1358786231445_13 , 另外又新增一個 className [yui3-widget] , style 的部分,則是因為我 new sampleWidget 這個物件的時候,指定了 height = 50px ,YUI 也會在 render 的時候,一起産生。

其它 Method

  • widget.render() , fire event: RENDER
  • widget.hide() : 增加 classname: yui3-sample-hidden (widget name = sample)
  • renderer : call _renderUI(), renderUI() , _bindUI(), bindUI()
  • _renderUI : call _renderBoxClassNames , _renderBox


目前回應 Comments(1 comments)

  • 小鬼 2013/12/04

    請教版主,
    widget 與 module 的差別在哪裡?

    Reply

    Admin

    YUI 的 Module 其實只是對程式的分割,當你在製作一個大型網站的時候,因為  Javascript 程式碼很多,不可能全部都寫在同一支檔案上,通常我們會分成多個檔案,每一個檔案只會有一小部分的 Javascript ,但是多個檔案的情形下,變數的命名很容易會有衝突,而 YUI Module 提供 YUI.add("module", function(Y){}) 的方式,讓你可以把程式碼寫在這個 function 裡,在 Module 裡的變數是獨立的,不會跟其他的 Module 變數有所衝突。
     
    YUI Widget  就如同這篇文章所介紹的,Widget 是一個 html + css + Javascript 的組合,Widget 的 Javascript 程式碼會包在 Module 之內,以防止變數命名衝突發生。
     

回應 (Leave a comment)