avalon2的vm是一个非常重要的东西,其设计原型最初脱胎于knockout.js,但到avalon1.6中,终于寻得自己的方案,更精简,更易用,更魔幻。

vm是一种特殊的数据结构,看起来像普通对象,但它大部分属性都被重写了,从而实现“操作数据即操作视图”的效果。我们在定义vm时,一般需要定义$id,其次是其他业务数据属性,它们都是来自后端的数据表。在1.4,1.5中,还有一个叫$skipArray的数组,用于方置一些只用同步一次视图的属性名,这是为了提高性能。因为将普通属性转换能同步视图的特殊属性,我们一般称之为监控属性(knockoutjs是这么叫的),其真正术语叫访问器属性。此外1.4与knockout一样,能定义计算属性,但2.0已经废掉,这里就不详述了!

  • $id vm的ID名,用于ms-controller
  • $skipArray, 数组, 用于指定那些属性不用转换监控属性, 这个在定义时指定, 生成后的vm并不存在。
  1. var vm = avalon.define({
  2. $id: 'test',
  3. a: 11,
  4. b: 22
  5. })
  6. vm.$watch('a', function(newValue, oldValue){
  7.  
  8. })
  9.  
  10. console.log(vm)

打开控制台,我们还会发现vm多出一些特殊属性,它们都是以$开头的

  • $events, 用于放我们的$watch回调
  • $fire, 用于触发某一个属性的所有回调
  • $watch, 用于监听某个属性的变化,当它变化时,将对应回调依次执行
  • $hashcode, $id可能有重复,但$hashcode不会重复
  • $track, 这是一个字符串,里面包括vm的所有属性名(除了那些内置的$开头属性),以;;隔开(这用于内部对象转换的)
  • $model, 返回纯净的JS对象

  • $element, 同名的ms-controller元素节点,这是应社区的要求,怎么通过vm得到元素
  • $render, 灵感来自react的render方法,用于生成对应的虚拟DOM树
  • accessors, 储存所有监控属性的定义,这在avalon.modern及avalon.next不存在,avalon.modern可以通过 Object.getOwnPropertyDescriptor得到访问器属性的定义,而avalon.next是使用Proxy实现vm,完全没有这方面的必要。

通常我们把avalon.define创建的vm叫顶层vm,内部使用masterFactory生成。

如果一个vm的属性 也是一个对象,那么它也会转换为vm,叫子级vm,或子vm,内部使用slaveFactory生成。

  1. var vm = avalon.define({
  2. $id: 'test',
  3. a: 11,
  4. b: {
  5. c: 22
  6. }
  7. })
  8.  
  9. 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上。

  1. var vm = avalon.define({
  2. $id: 'test',
  3. a: 11,
  4. arr: [{b:1},{b:2},{b:3}]
  5. })
  6. console.log(vm.arr)

如果vm的子级属性是一个数组,那么与1.4一样,转换为监控数组。监控数组就是一个push, unshift, splice, pop, shift, sort, reverse等方法被重写的数组。它在内部是由arrayFactory方法生成的。

如果监控数组的每个元素是一个对象,那么它们会转换为顶层vm, 由masterFactory生成,它们的$id名都叫做test.arr.*。这时你们明白$hashcode的用处了吧(如去重,排序)。

在avalon2,还提供了一个工厂来合并两个vm

  1.  
  2. TODO supply a title
  3.  
  4. var vm1 = avalon.define({
  5. $id: "test",
  6. a: 111
  7. })
  8. vm1.$watch('a', function(){
  9. console.log('vm1.a change')
  10. })
  11. var vm2 = avalon.define({
  12. $id: 'test2',
  13. b: 222
  14. })
  15. vm2.$watch('b', function(){
  16. console.log('vm2.b change')
  17. })
  18. var vm3 = avalon.mediatorFactory(vm1,vm2)
  19. //这个回调其实放在vm1.$events中
  20. vm3.$watch('a', function(){
  21. console.log('vm3.a change')
  22. })
  23. //这个回调其实放在vm2.$events中
  24. vm3.$watch('b', function(){
  25. console.log('vm3.b change')
  26. })
  27. console.log('------')
  28. vm3.a = 22
  29. vm3.b = 44
  30.  
  31. .ms-controller{
  32. display:none;
  33. }
  34. {{@a}}
  35.  

在chrome控制台中依次打印如下:

有人可能不理解为什么输出6次,我们先忽视调试信息。

  1. 首先前两个是vm3.a的值发生改变,由111变成22, 由于vm3.a实际上与vm1.a是同一个东西,因此都触发了。
  2. 其次中间两个是vm3.b的值发生变化,由222变成44,由于vm3.b实际上与vm2.b是同一个东西,因此都触发了。
  3. 最后是ms-duplex要将input.value同步为vm1,a这时为数字的22,但到了元素上,变成字符串的22, 于是又触了两下!

avalon.mediatorFactory是一个重要的方法,是实现ms-controller套嵌的关键,大家有兴趣的话可以看看其源码。

顶层vm masterFactory 供用户操作与保存回调与同步视图
子vm slaveFactory 承载更多用户数据
监控数组 arrayFactory 承载更多用户数据
内部vm mediatorFactory 容纳多个vm的数据与回调,并作为参数传入$render方法,生成新的虚拟DOM树

最后请大家点星加赞

avalon2学习教程02之vm的更多相关文章

  1. avalon2学习教程06样式操作

    avalon2的ms-css的变革思路与ms-attr一样,将多个操作合并成到一个对象里面处理,因此没有ms-css-name="value",只有ms-css="Obj ...

  2. avalon2学习教程15指令总结

    avalon的指令在上一节已经全部介绍完毕,当然有的语焉不详,如ms-js.本节主要总结我对这方面的思考与探索. MVVM的成功很大一语分是来自于其指令,或叫绑定.让操作视图的功能交由形形式式的指令来 ...

  3. avalon2学习教程14动画使用

    avalon2实际上没有实现完整的动画模块,它只是对现有的CSS3动画或jquery animate再包装一层. 我们先说如何用CSS3为avalon实现动画效果.首先要使用avalon.effect ...

  4. avalon2学习教程13组件使用

    avalon2最引以为豪的东西是,终于有一套强大的类Web Component的组件系统.这个组件系统媲美于React的JSX,并且能更好地控制子组件的传参. avalon自诞生以来,就一直探索如何优 ...

  5. avalon2学习教程12数据验证

    avalon2砍掉了不少功能(如ms-include,ms-data),腾出空间加了其他更有用的功能.数据验证就是其中之一.现在avalon2内置的验证指令是参考之前的oniui验证框架与jquery ...

  6. avalon2学习教程09循环操作

    avalon2的循环指令的用法完全改变了.avalon最早期从knockout那样抄来ms-each,ms-with,分别用于数组循环与对象循环.它们都是针对元素内容进行循环.后来又从angular那 ...

  7. avalon2学习教程08插入移除操作

    本节介绍的ms-if指令与ms-visible很相似,都是让某元素"看不见",不同的是ms-visible是通过CSS实现,ms-if是通过移除插入节点实现. ms-if的用法与1 ...

  8. avalon2学习教程05属性操作

    avalon2与avalon1的属性操作虽然都是使用ms-attr,但用法完全不一样. avalon1是这样操作属性的 其语法为 ms-attr-valueName="vmProp" ...

  9. avalon2学习教程 03数据填充

    数据填充是一个模版最基础的功能,直接从JSON(vm)取出数据,放到适当的位置上.在静态模板中,不区分文本与HTML,只看你的字符串是否有< >来决定生成文本节点与元素节点.但MVVM中, ...

随机推荐

  1. 20165312 C语言基础调查和JAVA学习展望

    C语言基础调查和JAVA学习展望 一.有关学习技能的经历 掌握一项技能,我认为最重要的是练习和认真程度. 我在上幼儿园的时候学过电子琴,上台表演过多次,但是三四年之后就半途而废了,后来小学毕业之后对钢 ...

  2. (转)Linux中设置服务自启动的三种方式

    有时候我们需要Linux系统在开机的时候自动加载某些脚本或系统服务 主要用三种方式进行这一操作: ln -s                       在/etc/rc.d/rc*.d目录中建立/e ...

  3. 解决ExtNET ExtJS 特定日期选择月份跳转导致无法选择月份的问题

    背景 项目使用 Ext.NET 2.2.0.40838 , 对应Ext JS4.2版本. 结果 2017/3/31 号的时候偶然间点日历选择控件选择2月,10月等月份突然就跳到3月份,9月份之类. 就 ...

  4. linux xml

    1:xml的基础语法,识别,创建xml文件 xml文件头:<?xml version="1.0" encoding="utf-8"?> 必须要有且 ...

  5. 线程守护进程与GIL

    为何要用多线程 多线程指的是,在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程.详细的讲分为4点: 1. 多线程共享一个进程的地址空间 2. 线程比进 ...

  6. Java - 32 Java 多线程编程

    Java 多线程编程 Java给多线程编程提供了内置的支持.一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 多线程是多任务的一种特别 ...

  7. CS229 6.10 Neurons Networks implements of softmax regression

    softmax可以看做只有输入和输出的Neurons Networks,如下图: 其参数数量为k*(n+1) ,但在本实现中没有加入截距项,所以参数为k*n的矩阵. 对损失函数J(θ)的形式有: 算法 ...

  8. mySQL InnoDB 的性能问题讨论

    https://ncisoft.iteye.com/blog/34676 https://www.douban.com/note/245895324/ MySQL最为人垢病的缺点就是缺乏事务的支持,M ...

  9. Heap Allocation Profiles (heap=sites)

    基于JDK-6,使用的类不同,展示的信息可能不同,内容一样的javac -J-agentlib:hprof=heap=sites Hello.java percent live alloc’ed st ...

  10. 《汇编语言 基于x86处理器》第十章结构和宏部分的代码

    ▶ 书中第十章的程序,主要讲了结构与宏的使用 ● 代码,使用结构,对比是否对齐的性能差距 INCLUDE Irvine32.inc INCLUDE macros.inc structN STRUCT ...