[TOC]javascript
avalon擁有兩大利器,強大的組件化功能以應對複雜牆問題,頂級的虛擬DOM機制來解決性能牆問題。html
組件可謂是指令的集合,但1+1 > 2
!java
組件容器是一個佔位用的元素節點. 當avalon掃描到此位置上時將它替換成組件.react
在avalon2中有4類標籤能夠用做組件容器,分別是wbr, xmp, template, 及ms-開頭的自定義標籤.git
其兼容性以下github
元素 | 類型 | 說明 |
---|---|---|
wbr | 全部瀏覽器, 自閉合標籤 | 須要使用ms-widget來指定組件類型 |
xmp | 全部瀏覽器, 閉合標籤 | 須要使用ms-widget來指定組件類型,裏面可使用slot屬性元素 |
template | IE9+及W3C瀏覽器,閉合標籤 | 須要使用ms-widget來指定組件類型,裏面可使用slot屬性元素 |
ms-* | IE9+及W3C瀏覽器,閉合標籤 | 能夠省略ms-widget, 裏面可使用slot屬性元素 |
閉合標籤,好比
<div></div><a></a>
自閉合標籤,好比<input><img><br><link>
web
根據上表, 若是要兼容IE6-8, 那麼只能使用wbr, xmp來作組件容器ajax
若是不打算支持IE, 那麼使用template元素性能最好shell
若是追求語義化, 只支持IE9+及其餘現代瀏覽器,則使用ms-*自定義標籤.npm
xmp元素裏面不能放xmp, template元素裏面不能放template,這是html規範,就像script元素裏面不能放script, textarea元素裏面不能放textarea. 但咱們能夠在這些元素裏面直接放ms-*自定義標籤.
<xmp ms-widget="{is:'ms-dialog'}"> <ms-title slot="title">{{@title}}</ms-title> <xmp>
若是咱們想在頁面上使用組件,須要用組件容器與ms-widget指令聲明一下.
<wbr ms-widget="{is:'ms-button'}" />
這就是聲明使用一個按鈕組件.
固然還有其餘三種方式
<xmp ms-widget="{is:'ms-button'}" /></xmp> <template ms-widget="{is:'ms-button'}" /></template> <ms-button></ms-button>
自定義標籤都是閉合標籤,不能寫成下面這樣
<ms-button />
可是若是你的ms-button是放在xmp或template下面,則容許這樣寫.
<xmp ms-widget="{is:'ms-dialog'}"> <ms-title slot="title" /> <div slot="content">這是彈出層的內容</div> <div slot="footer"> <ms-button :widget="@ok" /> <ms-button :widget="@ng" /> </div> <xmp>
因爲組件名在高級瀏覽器中,能夠做用自定義標籤的標籤名.而HTML標籤在HTML5中有嚴格的規定, 只能出現 $,-,數字與英文單詞, 而且只能以字母開頭, 中間必須有'-'.
此外,爲了方便avalon辨識這個標籤名是否爲一個數組,avalon強制規定以ms-開頭, 即
ms-button, ms-date-picker, ms-router-link
可是若是你不用自定義標籤聲明組件,使用ms-widget配置對象來聲明組件呢, 你就能夠突破部分限制, 能夠不以ms-
開頭
logger, date-picker, router-link
<wbr ms-widget="{is:'texer'}" />
ms-widget
能夠省略成:widget
,它應該對應一個對象, 即配置對象.
avalon2 的默認配置項比avalon1.5 少量多。全部組件通用的配置項
is, 字符串, 指定組件的類型。若是你使用了自定義標籤,從標籤名就得知組件類型,則能夠省略。
$id, 字符串, 指定組件vm的$id,這是可選項。若是該組件是位於SPA的子頁裏面,也請務必指定此配置項,能大大提升性能。
define, 函數, 本身決定如何建立vm,這是可選項。
onInit, onReady, onViewChange, onDispose四大生命週期鉤子。
其餘組件須要傳入的屬性與方法,也能夠寫配置對象中。
爲了方便傳數據,ms-widget也像ms-class那樣能對應一個數組。
<wbr ms-widget="[@allConfig, {$id: 'xxx_'+$index}]"/>
此外, 若是你的組件是位於SPA的子頁面中,或是由ms-html動態生成。
但組件對應的真實節點被移出DOM樹時,該組件會被銷燬。爲了進一步提升性能,你能夠在組件容器中定義一個cached屬性,其值爲true,它就能常駐內存。
<wbr cached="true" ms-widget="[@allConfig, {$id: 'xxx_'+$index}]"/>
用了cached時,必須指定$id配置項。
爲了方便傳入很長的HTML格式的參數,web components規範發明了slot機制。
avalon使用了一些黑魔法也讓舊式IE瀏覽器支持它。
通俗來講, 咱們用組件容器爲組件佔位, 咱們也用插槽容器爲插卡元素佔位.
咱們看一下ms-view
組件的定義與聲明:
avalon.component('ms-view',{ template:"<div class="view"><slot name="content" /></div>", defaults: { content: "" } })
<div ms-controller='test'> <ms-view> <div slot="content">這是子視圖的內容</div> </ms-view> </div>
<slot name="content" />
叫作插槽元素,用來佔位的,實際上它在內部會轉換兩個註釋節點
<div class="view"> <!--slot:content--> <!--slot-end:--> </div>
組件容器中的帶slot屬性的元素, <div slot="content">這是子視圖的內容</div>
,就是插卡元素. 插卡元素最終會移動到組件對應的註釋節點中去.
<div class="view"> <!--slot:content--> <div slot="content">這是子視圖的內容</div> <!--slot-end:--> </div>
咱們能夠對插卡元素使用除ms-if外的各類指令,如ms-for
<xmp :widget="{is:'ms-tabs',buttons: @buttons,tabs:@tabs}"> <div ms-for='(index,tab) in @tabs' ms-visible='index === @activeIndex ' slot='tabs' >{{tab}}</div> </xmp>
中文叫單插槽或匿名插槽. 這是插槽機制的一個特例.
好比咱們作一個按鈕組件:
avalon.component('ms-button', { template: '<button type="button"><span><slot name="buttonText" /></span></button>', defaults: { buttonText: "button" } })
那麼外面要這麼使用
<ms-button><b slot="buttonText">xxx</b></ms-button>
事實上咱們只想傳入一個文本,不想傳入b元素.這樣定義太冗餘了.
就像button標籤,能夠直接
<button>按鈕</button>
因而就有單插槽機制. 它要求組件
內部只有一個地方能夠插東西, 而且將組件容器
的全部孩子或文本都做爲一個插卡.
咱們看一下新的定義與聲明方式:
avalon.component('ms-button', { template: '<button type="button"><span><slot /></span></button>', defaults: { buttonText: "button" }, soleSlot: 'buttonText' })
<ms-button>xxx</ms-button>
avalon掃描後, 生成的組件是這個樣子:
<button type="button"> <span> <!--slot:buttonText--> xxx <!--slot-end:--> </span> </button>
插槽機制能夠解決咱們傳入大片內容的難題, 多個slot元素擁有同一個name值。
avalon定義組件時是使用avalon.component方法。
avalon.component方法有兩個參數,第一個標籤名,必須以ms-開頭;第二個是配置對象.
配置對象裏也有4個配置項
template,自定義標籤的outerHTML,它必須是用一個普通的HTML元素節點包起來,裏面可使用ms-*等指令
defaults,用來定義這個組件的VM有什麼屬性與方法
soleSlot,表示組件只有一個插槽,會將組件容器的全部孩子都移到這裏來 ,可選。
getTemplate, 用來修改template, 依次傳入vm與template, 返回新的模板, 可選。
avalon.component('ms-pager', { template: '<div><input type="text" ms-duplex-number="@num"/><button type="button" ms-on-click="@onPlus">+++</button></div>', defaults: { num: 1, onPlus: function () { this.num++; } }, getTemplate: function(vm, template){ return template.replace('ms-on-click','ms-on-mousenter') } });
var widgetVTree = widgetName(widgetOptions, slots, getTemplate(template)) /* widgetName: ms-widget中的is配置項或自定義標籤的標籤名 widgetOptions: ms-widget配置項 slots: 全部插卡元素組成的對象 getTemplate: 組件定義中getTemplate配置項 template: 組件定義中template配置項 widgetVTree: 組件的虛擬DOM, */
avalon2組件擁有完善的生命週期鉤子,方便你們作各類操做。
avalon2 | web component | react | |
---|---|---|---|
初始化 | onInit | createdCallback | getDefaultProps |
插入DOM樹 | onReady | attachedCallback | componentDidMount |
視圖變化 | onViewChange | attributeChangedCallback | componentDidUpdate |
移出DOM樹 | onDispose | detachedCallback | componentWillUnmount |
onInit,這是組件的vm建立完畢就當即調用時,這時它對應的元素節點或虛擬DOM都不存在。只有當這個組件裏面不存在子組件或子組件的構造器都加載回來,那麼它纔開始建立其虛擬DOM。不然原位置上被一個註釋節點佔着。
onReady,當其虛擬DOM構建完畢,它就生成其真實DOM,並用它插入到DOM樹,替換掉那個註釋節點。至關於其餘框架的attachedCallback, inserted, componentDidMount.
onViewChange,當這個組件或其子孫節點的某些屬性值或文本內容發生變化,就會觸發它。它是比Web Component的attributeChangedCallback更加給力。
onDispose,當這個組件的元素被移出DOM樹,就會執行此回調,它會移除相應的事件,數據與vmodel。
avalon會先將組件容器轉換爲一個渲染函數,傳入組件VM,成一個虛擬DOM(shellRoot)
再將組件定義中的template轉換爲第二個渲染函數,傳入組件VM,成一個虛擬DOM(component)
而後將shellRoot的最外層元素的全部屬性合併到component的最外層的元素上.
再將shellRoot中的插卡元素, 插入到component中的插槽元素的位置上.
將component變成真實DOM,替換組件容器.
請移步到Github
npm install avalon-promise
npm install mmPequest
npm install mmDux
雖然avalon2已經擁有ms-effect指令,但那是基於CSS3的,在IE6-8下是須要JS庫來支持
mmAnimate
npm install mmAnimate
npm install ms-modal
npm install ms-pager
npm install ms-tabs