avalon2組件的相關概念詳解

[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>

soleSlot機制

中文叫單插槽匿名插槽. 這是插槽機制的一個特例.

好比咱們作一個按鈕組件:

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

官方組件集

Promise

mmPromise

npm install avalon-promise

ajax組件

mmRequest

npm install mmPequest

redux事件派發組件

mmDux

npm install mmDux

路由組件

mmRouter

動畫組件

雖然avalon2已經擁有ms-effect指令,但那是基於CSS3的,在IE6-8下是須要JS庫來支持
mmAnimate

npm install mmAnimate

彈窗組件

ms-modal

npm install ms-modal

分頁組件

ms-pager

npm install ms-pager

切換卡組件

ms-tabs

npm install ms-tabs
相關文章
相關標籤/搜索