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了!