avalon2的vm是一个很是重要的东西,其设计原型最初脱胎于knockout.js,但到avalon1.6中,终于寻得本身的方案,更精简,更易用,更魔幻。javascript
vm是一种特殊的数据结构,看起来像普通对象,但它大部分属性都被重写了,从而实现“操做数据即操做视图”的效果。咱们在定义vm时,通常须要定义$id,其次是其余业务数据属性,它们都是来自后端的数据表。在1.4,1.5中,还有一个叫$skipArray的数组,用于方置一些只用同步一次视图的属性名,这是为了提升性能。由于将普通属性转换能同步视图的特殊属性,咱们通常称之为监控属性(knockoutjs是这么叫的),其真正术语叫访问器属性。此外1.4与knockout同样,能定义计算属性,但2.0已经废掉,这里就不详述了!html
var vm = avalon.define({ $id: 'test', a: 11, b: 22 }) vm.$watch('a', function(newValue, oldValue){ }) console.log(vm)
打开控制台,咱们还会发现vm多出一些特殊属性,它们都是以$开头的java
一般咱们把avalon.define建立的vm叫顶层vm,内部使用masterFactory生成。react
若是一个vm的属性 也是一个对象,那么它也会转换为vm,叫子级vm,或子vm,内部使用slaveFactory生成。git
var vm = avalon.define({ $id: 'test', a: 11, b: { c: 22 } }) console.log(vm.b)
vm.b就是一个子vm,它与顶层vm有些区别,首先其$id为顶层vm的$id加上其属性名构成, 即"test.b"。它少了一些系统属性,如$element, $render, $watch, $fire, $events(这个在avalon.next存在),能够说是一个轻量的vm。它的数据发生改动时,它不会本身处理$watch回调,而是交由顶层的vm来处理,由于全部回调都放在顶层vm的$events上。github
var vm = avalon.define({ $id: 'test', a: 11, arr: [{b:1},{b:2},{b:3}] }) console.log(vm.arr)
若是vm的子级属性是一个数组,那么与1.4同样,转换为监控数组。监控数组就是一个push, unshift, splice, pop, shift, sort, reverse等方法被重写的数组。它在内部是由arrayFactory方法生成的。chrome
若是监控数组的每一个元素是一个对象,那么它们会转换为顶层vm, 由masterFactory生成,它们的$id名都叫作test.arr.*。这时大家明白$hashcode的用处了吧(如去重,排序)。后端
在avalon2,还提供了一个工厂来合并两个vm数组
TODO supply a title {{@a}}数据结构
在chrome控制台中依次打印以下:
有人可能不理解为何输出6次,咱们先忽视调试信息。
avalon.mediatorFactory是一个重要的方法,是实现ms-controller套嵌的关键,你们有兴趣的话能够看看其源码。
顶层vm | masterFactory | 供用户操做与保存回调与同步视图 |
子vm | slaveFactory | 承载更多用户数据 |
监控数组 | arrayFactory | 承载更多用户数据 |
内部vm | mediatorFactory | 容纳多个vm的数据与回调,并做为参数传入$render方法,生成新的虚拟DOM树 |
最后请你们点星加赞!