avalon的指令在上一节已经全部介绍完毕,当然有的语焉不详,如ms-js。本节主要总结我对这方面的思考与探索。

MVVM的成功很大一语分是来自于其指令,或叫绑定。让操作视图的功能交由形形式式的指令来代劳。VM,成了一个大管家。它只一个反射体。我们对它的操作,直接影响到视图。因此俗称“操作数据即操作视图”!至于它是怎么影响视图,avalon视其版本的不同,也有不同的解法。如果抛开avalon,纵观世上所有MVVM框架,大抵有如下几种方式

  1. 函数wrapper:将原数据对象重新改造,所有属性都变成一个函数,有参数时就是赋值,进行视图同步与回调派发,没有参数时就取值,进行依赖收集。如knockout.js。
  2. 上帝getter,setter: 将原数据对象重新包装,但对数据的操作必须经过统一的set,get方法。在set方法进行视图同步与回调派发,没有参数时进行依赖收集。如reactive.js。如果放松要求,react也是这种方式,它使用setState进行视图同步。但它们依赖收集的过程。
  3. 函数编译及脏检测:将VM放到一个函数体内,取toString重新编译,内部是第一种方式。如angular.
  4. Object.defineProperty属性劫持:前三种的用户体验非常糟,于是有了这种方式,最初我是从emberjs中学来的。avalon,vue及其他后来的MVVM框架都是使用这种方式。在赋值时执行内部的setter方法,进行视图同步与回调派发,在取值时执行内部的getter方法,进行依赖收集。
  5. Object.observe对象监控: 这个API很短命,因此没几个MVVM框架用上它。由于无法进行依赖收集,需要别辟蹊径!
  6. Proxy对象监控:Object.observe对用户的行为监控是很弱的,并且是异步的,不够友好。于是有了这个新宠物。但这其实也不算新宠,firefox4就存在了。它能对数据赋值,取值,遍历,删除等各种行为都能监控到,了解Object.defineProperty 不能监控新属性的难题。在avalon2 中,就有一分支使用它实现。avalon2一共使用了VBScript, Object.defineProperty, Proxy实现vm。并且它没有进行依赖数据,而是将整个视图编译成一个大函数,每次数据变动,都重新执行这个函数,产生虚拟DOM,前后虚拟DOM进行diff,最后全量更新。这思路从react.js学来的。

上面说了,既然使用编译整个视图成模板函数这一手段,我们就尽量让这函数轻量化。位于这视图上的所有指设也要简化,方便在对应位置上代入VM中的属性。在avalon1及其他MVVM框架,都是使用动态依赖收集方式来推断指令中的某个单词是否为vm中的某个属性,这性能耗损比较严重。在avalon2直接让用户在属性名前加上 @ 符号,人工优化这步骤了。此外,指令属性值的设计原则也很明确,就是方便转换一个函数,返回对象或对象数组(如ms-attr,ms-css,ms-widget,ms-effect,ms-class,ms-hover,ms-active,ms-for),少量的返回布尔或字符串等直接可用于JS 语句的字面量。除了ms-for与过滤器,没有其他特殊语法。


除了ms-duplex,ms-on,原则上不再出来ms-xxx-yyy这样的指令。ms-后面只跟一个单词就够了,不用再加-及其他单词。

各种指令的优先级如下:
ms-for, ms-widget, ms-effect, ms-if…………其他指令(按指令名的charCodeAt排序)…………ms-duplex!

ms-duplex是最后,因此再不用担心它与其他指令冲突的问题。

指令的更新时机有两个,一个是位于此标签之间的所有孩子执行之前,一个是位于此标签之间的所有孩子执行之后。亦即change, afterChagne列队。有兴趣的话,可以阅览这里的源码。

想自定义指令,可以使用avalon.directive方法,第一个为指令名,第二个是定义体,里面至少有parse, diff, update三个方法。自己参看css指令,编写指令吧。

//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//安全的遍历VBscriptif (Array.isArray(a)) {//转换成对象a = avalon.mix.apply({}, a)}if (typeof p !== 'object') {//如果一开始为空src.changeStyle = src[name] = a} else {var patch = {}var hasChange = falsefor (var i in a) {//diff差异点if (a[i] !== p[i]) {hasChange = truepatch[i] = a[i]}}if (hasChange) {src[name] = asrc.changeStyle = patch}}if (src.changeStyle) {update(src, this.update)}}delete copy[name]//释放内存},update: function (dom, vdom) {var change = vdom.changeStylevar 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了!

avalon2学习教程15指令总结相关推荐

  1. avalon2学习教程04显示隐藏处理

    今天的主角是ms-visible,它的效果类拟于jQuery的toggle,如果它后面跟着的表达式为真值时则显示它所在的元素,为假值时则隐藏.不过显示不是 display:none这么简单,众所周知, ...

  2. avalon2学习教程11数据联动

    在许多表单应用,我们经常遇到点击一个复选框(或下拉框)会引发旁边的复选框(或下拉框)发生改变,这种联动效果用avalon来做是非常简单的.因为avalon拥有经典MVVM框架的一大利器,双向绑定!绝大 ...

  3. avalon2学习教程11数据联动 1

    在许多表单应用,我们经常遇到点击一个复选框(或下拉框)会引发旁边的复选框(或下拉框)发生改变,这种联动效果用avalon来做是非常简单的.因为avalon拥有经典MVVM框架的一大利器,双向绑定!绝大 ...

  4. 深度学习教程(6) | 神经网络优化算法(吴恩达·完整版)

    作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/35 本文地址:https://www.showmeai.tech/article-d ...

  5. 深度学习教程(10) | 卷积神经网络解读(吴恩达·完整版)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/35 本文地址:http://www.showmeai.tech/article-det ...

  6. Python学习教程(Python学习路线):Day08-面向对象编程基础

    Python学习教程(Python学习路线):面向对象编程基础 活在当下的程序员应该都听过"面向对象编程"一词,也经常有人问能不能用一句话解释下什么是"面向对象编程&qu ...

  7. python sorted下标_Python学习教程(Python学习路线):第七天-字符串和常用数据结构

    Python学习教程(Python学习路线):字符串和常用数据结构 使用字符串 第二次世界大战促使了现代电子计算机的诞生,当初的想法很简单,就是用计算机来计算导弹的弹道,因此在计算机刚刚诞生的那个年代 ...

  8. Java学习教程,Java从入门到精通,全套Java视频教程+笔记+配套工具

    目录 一.大纲 一.Java基础 二.计算机基础 三.工具的使用 四.数据库 五.web前端 六.JavaWeb 七.框架 八.互联网分布式技术 发现身边很多自学java却放弃的,真的挺可惜的. 白白 ...

  9. C++学习教程从零开始(三)——何谓变量

    2019独角兽企业重金招聘Python工程师标准>>> C++学习教程从零开始(三)--何谓变量 本篇说明内容是C++中的关键,基本大部分人对于这些内容都是昏的,但这些内容又是编程的 ...

最新文章

  1. ExtJs 备忘录(3)—— Form表单(三) [ 数据验证 ]
  2. 不会这些搜索技巧,真别说你懂 GitHub!
  3. 南达科他州立大学计算机科学,关于举行南达科他州立大学Srinivas Janaswamy博士学术报告的通知...
  4. 关于web项目当中的mybatis的xml 文件的配置启动报错的解决。
  5. Sql Server查询语句的一些小技巧
  6. 2019年的第三场LiveVideoStackCon有何不同?
  7. n个数里找出前m个数(或者 从10亿个浮点数中找出最大的1万个)
  8. 没有写入hosts文件权限
  9. python发动机悬置解耦计算-按重心处整车坐标系解耦
  10. 解决Latex正文中的参考文献有许多[0]的情况
  11. 家卫士扫地机器人好吗_扫地机器人哪个牌子好?市场最全智能扫地机器人品牌解析_扫地机器人...
  12. 深圳华为 C++面试题
  13. Qt容器类之三:通用算法
  14. DOTween 使用方法
  15. NB-IOT (2)---移远BC26模块模组快速入门
  16. CentOS7常用工具包安装
  17. 7714天,王小川正式卸任搜狗CEO!网友:别了。。。
  18. 计算机usb显示不出来怎么办,U盘在电脑上显示不出来怎么办
  19. 【技术贴】解决前台js传参中文乱码
  20. 如何用python制作三维动画_用Python制作3D动画

热门文章

  1. 同步Android与PC的时间
  2. android中AsyncTask和Handler对比
  3. 简单的ASP.NET无刷新分页
  4. 家庭组计算机无法,【求助】Windows无法从该家庭组中删除你的计算机
  5. CSDN绑定GitHub账号
  6. 存储过程 not supported yet_让我们来看看+Redis如何存储和计算一亿用户的活跃度
  7. 测试电视是不是4k的软件,怎么判断4K电视真假?教你快速检测的方法!
  8. websocket 发送给前端一个对象_前端WebSocket封装
  9. Lombok中@Data注解 @ToString注解 @NoArgsConstructo注解 @AllArgsConstructor注解
  10. 了解jvm自动内存分配和内存自动回收的重要性