Widget的實例屬性
Widget有兩個重要屬性BOUNDING_TEMPLATE 和 CONTENT_TEMPLATE。初始值都是”<div></div>”,這為多數(shù)widget提供一個標(biāo)準(zhǔn)html結(jié)構(gòu),包含雙層嵌套的div。但并不是所有的widget都適用,比如按鈕使用<span> <a></a></span> 而不是<div><div></div></div>結(jié)構(gòu),其實Widget不強(qiáng)制要求使用一個大容器(contentBox),這兩個屬性可以使用任意html標(biāo)簽,比如我用a來描述按鈕 BOUNDING_TEMPLATE: ‘<a>’, CONTENT_TEMPLATE: null,</a>
在你不需要contentBox的時候就將其設(shè)置為null,這時contentBox的配置會繼承自boundingBox。不要將widget的所有HTML都放在這兩個屬性中,這兩個屬性中的元素要盡量簡單,在renderUI中使用代碼創(chuàng)建其余的html標(biāo)簽。Widget會給所有你指定的標(biāo)簽加上id和class,形式諸如yui3-xxxx, yui3-xxxx-visible 或 yui3-xxxx-disabled,其中xxxx是小寫的NAME屬性。
Widget實例方法
Widget的初始化有多個步驟,除了會在對象實例化時調(diào)用initializer(構(gòu)造函數(shù))外,在銷毀時也會調(diào)用destructor函數(shù)(析構(gòu)函數(shù)),這兩個方法都繼承自Base。Widget又增加了renderUI, bindUI, syncUI三個函數(shù),在widget的render方法被調(diào)用時,這三個函數(shù)會依次執(zhí)行。
renderUI負(fù)責(zé)生成widget最基本的HTML骨架,包括boundingBox和contentBox,如果考慮到漸進(jìn)增強(qiáng), renderUI會先檢查元素是否已存在于DOM中,這是因為如果設(shè)置HTML_PARSER屬性,配置屬性中定義的元素會被事先生成好。如果元素沒有事先生成,我們才需要通過renderUI來創(chuàng)建。
最簡單的生成HTML的方法(假設(shè)沒有使用漸進(jìn)增強(qiáng))就是使用Y.Node.create方法: renderUI: function () { var cbx = this.get(CBX); cbx.append(Y.Node.create(Y.substitute(Y.Xxxx.TEMPLATE, CLASS_NAMES))); },
這段代碼的運行需要特定的上下文,首先,要聲明常量CBX(見本篇文章第一個代碼塊),其次,widget所需的模塊都加載完全,加載widget之前會自動加載其依賴的Node, Y.substitute是可選模塊,如果需要則要把’substitute’ 加入到requires中。此外還要有一個作為widget內(nèi)容模板的名為TEMPLATE的靜態(tài)變量,你可以和其它靜態(tài)成員一起定義(通過ATTRS定義)它。最后常量CLASS_NAMES應(yīng)當(dāng)也已經(jīng)事先定義好了。
我通常在模塊開頭,和BBX,CBX一起定義CLASS_NAMES(見本文第一個代碼塊): var BBX = ‘boundingBox’, CBX = ‘contentBox’, NAME = ‘button’, // other constants and shortcuts …. YCM = Y.ClassNameManager.getClassName, getClassName = function () { var args = Y.Array(arguments); args.unshift(NAME); return YCM.apply(this, args).toLowerCase(); }, LABEL = ‘label’, PRESSED = ‘pressed’, ICON = ‘icon’, CLASS_NAMES = { pressed: getClassName(PRESSED), icon: getClassName(ICON), label: getClassName(LABEL), noLabel: getClassName(‘no’, LABEL) };
CLASS_NAME為一個object常量,其中的屬性值由ClassNameManager(包含在Widget中)生成。在以上代碼中,我先聲明一個指向Y.ClassNameManager.getClassName的縮寫YCM,然后聲明一個只能在模塊內(nèi)部訪問的私有函數(shù)getClassName,這個函數(shù)的功能與Widget中的同名函數(shù)getClassName的功能很類似,只是widget中的getClassName是個靜態(tài)函數(shù),可以用來生成靜態(tài)變量。CLASS_NAMES中表示樣式名的屬性值就是用它生成的,F(xiàn)在,我就可以這樣定義TEMPLATE中的樣式名了: TEMPLATE: ‘<label>’,</label>
這還不夠,我還想將其它的值比如配置屬性中的值加入模板中。可以這樣做: this.get(CBX).append(Y.Node.create(Y.substitute(TEMPLATE , CLASS_NAMES, Y.bind(function (key, suggested, arg) { return (key === ‘_’?this.get(arg):suggested); },this))));
我給Y.substitute增加了第三個參數(shù),一個函數(shù)。通常,Y.substitute中的占位符是由一對花括號包圍的字符串,如果其中有空格,占位符就會被一分為二?崭袂懊娴牟糠譃閗ey,空格后的部分為可選參數(shù)。當(dāng)Y.substitute的第三個參數(shù)是一個函數(shù)時,這個特性十分有用。比如在此例中,第一個參數(shù)是key,第二個參數(shù)是用于替換的內(nèi)容,此例中是CLASS_NAME,第三個是可選參數(shù)。所以在上面的語句之后,我可以這樣使用模板: TEMPLATE: ‘<label for="”{_" />’,
Y.substitute在執(zhí)行時先碰到{label},開始在CLASS_NAME中搜索,并找到對應(yīng)值‘yui3-button-label’。然后以‘label’, ‘yui3-button-label’ 和 undefined為參數(shù)調(diào)用替換函數(shù)。因為key不等于’_’,所以函數(shù)返回第二個參數(shù)中值,即原始的樣式名。當(dāng)遇到{_ id}時,因為在CLASS_NAMES中沒有’_’屬性,所以會以傳入?yún)?shù)‘_’, undefined 和 ‘id’調(diào)用替換函數(shù),函數(shù)會從配置屬性中讀取’id’的值。在遇到占位符{_ value}時函數(shù)將執(zhí)行同樣的操作。
出處:Taobao.com UED Team
責(zé)任編輯:bluehearts
上一頁 使用YUI 3開發(fā)Web應(yīng)用的訣竅 [4] 下一頁 使用YUI 3開發(fā)Web應(yīng)用的訣竅 [6]
◎進(jìn)入論壇網(wǎng)頁制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評論。
|