avalon最早发布于2012.09.15,当时还只是mass Framework的一个模块,当时为了解决视图与JS代码的分耦,参考knockout开发出来。 它的依赖收集机制,视图扫描,绑定的命名data-*都与knockout差不多。它总共900行。
当时的理论体现在我在注释的这一段话:
JS UI Component 最终还是通过 HTML 来描述界面,当 js object 的数据发生变化或者执行某个动作时, 需要通知到对应的html,使其发生相应变化。于是js object 需要得到他在页面上对应的html的句柄, 通常做法,是在创建html的时候将createElement返回的句柄保存在js object 内部的某个变量中,或者赋值给html eLement一个唯一的ID,js object 根据这个ID来找到对应的HTML Element。同样, 当htm elementl的事件(例如onclick)要通知到相对应的 js object 或者回调js object的某个方法或属性时,也需要得到该js object的一个引用。我的意思是建立一种统一的规则,js object和他相对应的 html 能通过这种规则互相访问到对方。 建立这个关联以后,实现js object和 对应 html 的数据邦定和数据同步等问题就简单多了。
此后几个月还继续开发mass Framework的其他模块,还没有完全压注于MVVM。
2012.12.11发布0.2版,已经对knockout大多数源码进行消化,因此代码量降到730行。但功能还是残缺,不能绑定事件。
avalon也建立对应的概念来指导自己的发展:
位于VM中的原子监控者,依赖监控者,监控数组与绑定监控者。原子监控者对应ko的监控属性,它是由M中字段抽象而成,是一个函数。依赖监控者对应ko的依赖监控属性。在VM中,有些字段是建立在M的两个或多个字段的基础上。比如fullName 对应为 firstName+” ”+lastName,但在M中是找不到它的跟影,但它在视图中却又是一个独立的个体,有专门的文本域给它。绑定监控者是我独创的,它是根据视图中的数据绑定转化而为,在ko中这些依然称之为依赖监控属性。但这一类监控函数分明是真正用于连结DOM树与VM的。它通过框架提供的默认绑定器将自己中数据渲染到DOM中。它的结构比一般的依赖监控属性复杂多了。
依赖监控属性,knouckoutjs称之为Dependent Observables,在另一个著名的emberjs框架中,它叫做computed。在绑定监控者这类东西显然不需要返回值,它一般将比它低一级的原子监控者,依赖监控者当作事件回调来监控用户行为就行了。当用户改变了文本域的值,就相当于对这个原子监控者进行写入,从而引发整条依赖的更新。绑定监控者是与DOM树某个节点或某一些节点交道,当底层涌上来的变动要求它也刷新时,它就调用框架自带的绑定器进行干活。因此你看到绑定器都有一个叫update的函数,就是干这事。
位于视图中的声明式绑定,我使用bind,但也可以配置你喜欢的属性名。我个人喜欢称之为数据绑定,其实它还兼容流程控制,事件绑定的活儿。
位于视图中的动态模板,就是那些被声明式绑定圈起来的区域。动态模板与流程绑定最密切,它的实现好坏,牵及到最小化刷新的实现与内存的占有率。这个v2有实现比knouckout要高明多了
avalon在数据绑定上做了许多友好的改进,虽然与knouckoutjs一样支持表达式,是没有花括号的JSON。但它要求用户不用写双引号,这辛苦活由框架去实现了。
avalon的自带绑定器有text绑定,html绑定,value绑定,class绑定,style绑定,attr绑定,display绑定,checked绑定,with绑定,if绑定,unless绑定,foreach绑定
两天后发布0.3版,这是avalon第一次脱胎换骨,不再使用knockout将监控属性转换为函数的wrapper方式,改成Object.defineProperty构建它的双向绑定链,并且参考rivetsjs对绑定属性重新设计,不过绑定属性的前缀还是使用data-*
avalon在用户体验上第一次走上世界前列。不过当时avalon还不叫avalon,但我还是很满意,之后几个星期我写一个系列的教程(还有著名的todos例子)来介绍它。这期间还抽空看了bootstrap源码,也写了一个系列的相关博文,被网友们视为bs高手了。但mass Framework的升级工作还在进行,这占了我大量的时间。把自己做的事全部记录在博客就有这个好处,完成掌握自己的成长线路。我也不明白自己为什么如此纠结了mass Framework,它在各方面已经没有翻身的可能了。人付出越多,就不易放弃吧。这是赌徒心态。我的确在这上面耗了太多时间与精力,幸好它与avalon在许多技术之上有传承之处。像那些一会儿跳到JS,一会儿跳到java,一会儿跳到oc,这是多么惨的自杀行为啊。
2013.3.15起,我发表一篇叫《第一个vbscript程序》 的博文,开始着手解决avalon在旧式IE的兼容问题,切入点就是VBScript的set, get, let语句。
2013.04.25发布0.4,这是它第2次脱胎换骨,完全从mass Framework中独立出来,绑定属性改为我们熟悉的ms,并且拥有avalon.define、avalon.scan这两个方法。VBScript技术已经学以致用,Object.defineProperty终于在旧式IE实现兼容,这是其他MVVM不可想象的。
2013.05.1发布0.5,VM中添加 $id, $events, $watch, $unwatch, $skipArray, $xxx等属性与方法,可以说avalon的VM设计在这一版上定稿, 视图上添加ms-controller,ms-important, ms-skip等绑定,并且在内部整合一个迷你的jQuery对象,增强其DOM处理能力。
2013.05.07开始,编程重心转向avalon, 进入了小版本发布时代,0.6x起添加mouseleave, mouseenter的跨浏览器支持;添加ms-css绑定,添加addClass, removeClass, toggleClass方法; 并着手开发它的UI库,当时它的类名与结构都是用jquery UI搬过来的。那个时候攒到第一批国内用户了。
2013.05.25发布0.7,添加ms-template绑定(也就是日后的ms-incluce绑定) ms-attr绑定及全新的扫描机制。avalon与knockout在实现上越来越远,并且对其大东家mass Framework也在 0.7.2中正式分道扬镳。从博客园评论的分享来看, avalon的使用用户达到几十人了。0.7.3中去掉从knockout抄过来的ms-options绑定,VM里废弃$scope, $json, 重命名为更直观的$vmodel与$model。avalon源码也在这个版本里走无分号的风格。
2013.06.22发布0.8,由于换了新公司,接触到angular,尝试整合angular与requirejs,深深感到自带加载器的用处,于是将我发展了20多个版本号的并行加载器放进avalon里了。此外,avalon.mobile.js也要这个版本出现。0.81处理管道符与||运算符相混淆的BUG。 0.82里实现新parser。0.83可以配置插值表达式的界定符,ms-template改名为ms-include。 0.84规定ms-incude的值不能为空。 0.85改进ms-each。 以上就是0.8x上的一些重大改进,当然期间还肯定修改N多BUG,但这里介绍的都是对后面版本有重大影响的改进。 由于第一次有公司由我亲手操控来使用avalon,因此avalon在此期间的升级是相当频繁的。
2013.07.20发布0.9,引进ms-with。0.91fix BUG。 0.92添加ms-class的新风格支持。 0.93添加ms-duplex-radio绑定。 0.94引入绑定属性间的优先级,规则哪一个比哪个先执行。 0.95改进ms-with 深层绑定的实现。 0.96性能优化与 fix BUG。 以上就是0.8x上的一些重大改进,当然期间还肯定修改N多BUG,但这里介绍的都是对后面版本有重大影响的改进。 0.97性 王之三柱臣全部就位!
0.98修正大量BUG,添加ms-widget绑定,废弃ms-ui绑定。一些avalon用户做的东西可以放出来让大家了。 0.99为正式发布做冲刺,也修了大量BUG,移弃ms-bind绑定。 贯彻在0.9x中的梦魇是 ms-each、ms-with与ms-if这三个版本的升级与优化。ms-if的实现甚至在期间出现回滚。
2013.01.13发布1.0,这是一个重要的版本,因此在当时的博文也大肆宣扬一番 (GITHUB上的贡献人数达到8人,issues二百多个主题,各种组件也不断完善)。但它很短命,就像中华民国的临时大总统那样,只是一个标识—— 它过早地引进了一些不确定的实现方案。
2014.01.26发布1.1,直接没有1.0.x了。 许多东西都回到0.9x,并将期间发现的新解决方案加进去。它也有一些全新的东西, 如ms-if-loop绑定,data-with-sorted回调,data-duplex-changed回调。现在大家用到的API,基本上在这个版本上稳定下来。加之,用户量的庞大, 也让我不敢轻易改它的API。
2014.02.19发布1.2,直接没有1.1.x了。精力是优化,优化,优化! 如input.value被框架重写了,方便与第三方组件共存。循环绑定内部渐渐改进你们现在看到的模样。尤其在 1.2.4里, 各种代理VM已经使用池技术进行创建与回收(createWithProxy, createEachProxy); 1.2.5升级ms-widget; 1.2.6除了修BUG外,开始开发新一代UI库Oni。
总结这几个版本,0.8x, 0.9x都比较长命,那是我有工作有空闲开发avalon。1.0、1.1、1.2x比较短命, 因此我丢了饭碗,当然1.2x期间我又很快找到工作。
2014.05.26发布1.3,这预计也是个长命的版本,主要是性能改进与BUG fix。 全职开发框架的感觉真好。但公司要兼容IE6,各种奇葩的BUG层出不穷,从各种业务线汇总在我这里,因此avalon.mobile的升级其实一直拖滞。 这期间,我开发了avalon.observe.js,发掘了全新的静态收集依赖的技术,这本来是要应用于1.4x里的,但现在也没这时间了。三柱臣的升级也逼在眉睫。 avalon现在已经有20个贡献者了,但相对于外国的项目来说,这个数目也是微乎其微,希望能有更多人加入这个国产项目。我可以打票说, avalon是世界最好的MVVM框架,设计优良精巧,3000行的代码能实现其他MVVM框架用1W多行才能实现的效果。尤其是avalon对IE6上的兼容, 及已经对Object.observe的实战上,这也是其他MVVM框架所难企及的。