avalon的指令在上一節已經所有介紹完畢,固然有的語焉不詳,如ms-js。本節主要總結我對這方面的思考與探索。javascript
MVVM的成功很大一語分是來自於其指令,或叫綁定。讓操做視圖的功能交由形形式式的指令來代勞。VM,成了一個大管家。它只一個反射體。咱們對它的操做,直接影響到視圖。所以俗稱「操做數據即操做視圖」!至於它是怎麼影響視圖,avalon視其版本的不一樣,也有不一樣的解法。若是拋開avalon,縱觀世上全部MVVM框架,大抵有以下幾種方式css
上面說了,既然使用編譯整個視圖成模板函數這一手段,咱們就儘可能讓這函數輕量化。位於這視圖上的全部指設也要簡化,方便在對應位置上代入VM中的屬性。在avalon1及其餘MVVM框架,都是使用動態依賴收集方式來推斷指令中的某個單詞是否爲vm中的某個屬性,這性能耗損比較嚴重。在avalon2直接讓用戶在屬性名前加上 @ 符號,人工優化這步驟了。此外,指令屬性值的設計原則也很明確,就是方便轉換一個函數,返回對象或對象數組(如ms-attr,ms-css,ms-widget,ms-effect,ms-class,ms-hover,ms-active,ms-for),少許的返回布爾或字符串等直接可用於JS 語句的字面量。除了ms-for與過濾器,沒有其餘特殊語法。vue
除了ms-duplex,ms-on,原則上再也不出來ms-xxx-yyy這樣的指令。ms-後面只跟一個單詞就夠了,不用再加-及其餘單詞。java
各類指令的優先級以下:
ms-for, ms-widget, ms-effect, ms-if…………其餘指令(按指令名的charCodeAt排序)…………ms-duplex!node
ms-duplex是最後,所以再不用擔憂它與其餘指令衝突的問題。react
指令的更新時機有兩個,一個是位於此標籤之間的全部孩子執行以前,一個是位於此標籤之間的全部孩子執行以後。亦即change, afterChagne列隊。有興趣的話,能夠閱覽這裏的源碼。git
想自定義指令,可使用avalon.directive方法,第一個爲指令名,第二個是定義體,裏面至少有parse, diff, update三個方法。本身參看css指令,編寫指令吧。github
//css指令 var update = require('./_update') avalon.directive('css', { parse: function(cur, pre, binding) { cur[binding.name] = avalon.parseExpr(binding) }, diff: function (copy, src, name) { var a = copy[name] var p = src[name] if (Object(a) === a) { a = a.$model || a//安全的遍歷VBscript if (Array.isArray(a)) {//轉換成對象 a = avalon.mix.apply({}, a) } if (typeof p !== 'object') {//若是一開始爲空 src.changeStyle = src[name] = a } else { var patch = {} var hasChange = false for (var i in a) {//diff差別點 if (a[i] !== p[i]) { hasChange = true patch[i] = a[i] } } if (hasChange) { src[name] = a src.changeStyle = patch } } if (src.changeStyle) { update(src, this.update) } } delete copy[name]//釋放內存 }, update: function (dom, vdom) { var change = vdom.changeStyle var wrap = avalon(dom) for (var name in change) { wrap.css(name, change[name]) } delete vdom.changeStyle } })
裏面的parse(cur, pre, binding)方法是用於建立虛擬DOM, cur是經過vm.$render方法生成的新虛擬節點,pre是以前的虛擬節點,binding是當前指令抽象生成的綁定對象。數組
裏面的diff(copy, src, name)方法是用來比較先後兩個虛擬DOM。copy是新虛擬節點,src是以前的虛擬DOM,name爲指令的名字。當你用各類方式比較出這兩個虛擬DOM有差別,那你就可使用require('./_update')這個方法執行更新,更新方式爲指令的update方法。安全
2.1.0後,刷新機制有點改動,兩個節點比較出差別後當即更新真實DOM, 不像過去那樣所有比較再全量更新。
裏面的update(dom,vnode,parent)方法是用來更新真實元素的。
最後你能夠在avalon.directives對象中指到全部指令的定義。你也能夠在vm.$element.vtree中看到你生成的虛擬DOM樹。
既然avalon的指令已經所有介紹完了,所以你們如今能夠直接使用avalon2了!