2013年最后的收成:avalon1.0正式发布

大半年前我就说过,MVVM是前端究极的解决方案,因此之后我大多数时间都在折腾avalon,成立了专门的QQ群与感兴趣的一起讨论。感谢第一批吃螃蟹的人,avalon发展得很快,GITHUB上的贡献人数达到8人,issues二百多个主题,各种组件也不断完善。时至今日,我可以自豪地说许多静待1.0的看客说,它终于来了!

下面是avalon的生态系统:

avalon的核心是avalon.js或avalon.mobile.js(移动端版本,针对手机与平板)。其中avalon.js兼容到IE6,满足中国的特殊国情。avalon.mobile.js是支持移动端,IE10起支持,它使用了大量高级API,性能远超avalon.js,并添加了触屏事件的支持。

然后是三柱臣:mmRoutermmAnimatemmRequest,单页应用最常用的三个组件。

接着是拖放,事件代理,组件键,验证框架,高级定位机制,组合键等乱七八糟的,用于锦上添花的

最后是UI库,比较简单的控件都做出来,重头的树,GRID,多级菜单正在规划中……

说一下我的初衷啊。我最早是做企业级应用,大量的表单,大量的列表,迭代频繁,虽然JQ已经出来了,但业务逻辑与DOM显示逻辑混淆在一起,维护起来非常不爽。于是我开发了ejs这个前端模板。前端模板在当前还是一个很新的概念,因此我当时发布在博客园,许多人不解。但比起在JS文件里进行锁碎的字符串拼接,它就是易读易维护。QQ空间,淘宝那时也已经使用前端模板了。那是09年的事。之后,前端模板就像雨后春笋地不断涌现,性能越来越高。

转辗到盛大创新院后,做圈乐这个视频项目的瀑布流,与大牛们共事,用的是qwrap,接触了许多新概念。我的框架由dom Framework更名mass Framework,大量精力耗在选择器引擎与模块加载器的开发上。那时requirejs也是刚刚起步, Sizzle也很粗糙,因此这两个领域都有大量同类型产品。我大量读库,实力蒸蒸日上。创新院大裁员,我避风到SDO做盛大通行证,我深切地体会到现行开发模式的掣肘之处。我在创新院还可以用前端模板搞定渲染问题,但这是一对一的。盛大通行证一个逻辑面向不同的视图,要求务业逻辑与DOM渲染逻辑彻底分离,要不没法进行下去。当时我只有求助于JAVA的设计模式,各种解耦。像后端spring,早已想到这一点,因此才有IoC容器这样的东西出来。在处理渲染方面,它们有庞大的标签库,这是面向组件开发的拓路者。为了更好的控制标签的行为,微软从MVC的基础上发展起MVVM。MVVM用尽了23种设计模式,让我们轻松地操作一个叫VM的特殊数据源就能自动同步视图,这种机制被称之为绑定。绑定在微软的体系中分为三种one way, one time, two way。微软出身的Steve Sanderson搞出了第一个前端MVVM框架knockout。当时,09年,别说MVVM,MVC在前端也是新事物。前端MVC的风头从jQueryMVC转到backbone。我的注意力也停留在backbone身上。backbone有着后端JAVA MVC框架的优缺点,分类极细,责任明晰,但这也意味着繁锁,定义了许多类,但好像又什么也没干。其中这当中的类可以由框架自动生成。

模块加载器开发了十多个版本号, 我着手开发UI库了。这时愈感JQ的不便。UI是一种界面,很早以前人们就发现,干这活是声明式语言的强项。我们平时熟悉的javascript, C, C++, java则擅长做逻辑。于是才有前端模板这东西,将数据源往模板一套,界面就出来的。但之前的模板都属于字符串模板,无法对生成的元素节点进行后继操作。不过,据元素节点的innerHTML的能耐来看,它也不执行里面的script脚本。jquery的html可以打破这桎梏,其实也基于eval处理的。最终,knockout还是走入我的视野。很大一个原因是我一直活跃于博客园,博客园属于微软系,微软这个东西虽然难用一点,但在当时也算是至宝!

knockout是一个伟大的框架,一直很低调。作者是后端的人,很JS用得炉火纯青,大量的闭包,加之方法名,变量名是找C#那一套,名字巨长,搞得很难读懂它的源码。knockout的思想很简单,把用户的操作分成两部分,赋值与取值。赋值时,它就想办法同步视图。取值时,它就试图取得各种操作的依赖关系。有了依赖关系,就可以构成观察者模式,让视图同步成为可能。为了达到这目的,必须让框架知道当前进行的是什么操作,操作的作用方是谁。由于当时javascript访问器属性还鲜为人知,在旧式IE也有兼容难题。knockout取采的策略是将所有属性都转换为函数,根据函数有没有传参就可以辨识用户的行为了。对于数组,它是重写所有原生方法。avalon0.1-0.3就是追随knockout的步伐,逐渐了解它的其他概念与实现原理。比如说计算属性,取值属性,视图刷新函数,各种常用的绑定。

我之前谈如何写框架,就提到三个原则:复杂即错误,数据结构优于算法,出奇制胜。knockout的源码太复杂,导致想参与的人参与不进来。为了降低上手难度,你无论是从接口到实现,一定要条理清晰,不能到处是黑魔法与飞线方案。虽然avalon的源码只有一个文件,里面的条理是非常清晰的,并且刻意使用一些特殊的注释来隔开各个功能区。API尽可能少,许多重要的接口都不暴露出来,以后就可以随意折腾,不影响用户使用了。在厘清knockout的实现机理后,我就是由单纯的做轮子,转为发明新轮子。首先,属性转换为函数这一用法必须去掉,太扭曲了。ember的做法是使用两个上帝set, get方法来接管一切取值赋值操作,比knouckout好多了,但依然不直观。angular是直接对控制器等函数取toString进行编译,用法简单了,但实现难度非常高,加之它其余设计把这易用性泯灭了。于是我转来转去,还是求助于访问器属性解决了。这过程不是三言两语说得清的,但从结果来看,就是Object.defineProperties与VBScript类的Set, Get, Let语法。用户传入一个对象,然后我转出另一个跟它非常相似,好像只是添加了几个属性的对象,然后用户对它的属性进行操作,它就能同步视图,相当fantasy、 magic!易用性爆表了!

其次是绑定属性的设计, knockout是使用data-bind对应一个没有两端花括号的JSON对象字符串,看似规整划一,但这意味着内部要实现一个parser来转换。后起之秀的angular则友好多了,但最终我是参照了rivetsjs。缘由它的绑定风格能提供更多信息,更易分解,用户也很易理解。这样我就不用耗时实现一个庞大易出错的parser了。编码不同于建筑,BUG与规模是成比例增长,控制代码量是avalon在编写过程的一个重要指标,至少它还没有超过4000行。

最后根据用户的反馈,不断增加新功能,在增加新功能时不断引入BUG,然后修BUG,改好了,发现性能下降,于是提高性能。性能提高了,用户又提出新功能,然后……周而复始,不断与需求与BUG作斗争。这就像一个普通的产品的开发流程。不同的是,这个产品完全是属性于你,你有杀生大权,你能完全享受用户对你的赞誉。但反过来,其实我还是得感谢那些敢吃螃蟹的人,那些提BUG的人,那些pull request的人。正因为,这项目比mass Framework发展得顺利多了。它与最初的第一版几乎没有一行相同的代码,尽管我尽量避免API的改动,API最后也有改动了,变得更加精巧。

0.4-0.7是脱胎换骨时期,它一直留在mass Framework项目的内部。0.72独立出来,可以独挡一面了。这时不断改进绑定的实现,一直到0.94才稳定下来。难点在于ms-each, ms-repeat, ms-with, ms-widget(ms-ui), ms-if这五种API。它们的特点都是有节点插入操作。有的是插入了移除,移除了插入, 有的是循环生成一堆相同节点,有的是按照一个模板生成一个控件。由于绑定都有生命周期的概念,它的实现方式直接与它是否在DOM树挂钩,但如何是框架自己临时移出DOM树呢,于是就引发一系列问题了。幸好最终都解决了。这基本是靠时间磨出来的,今天想不出来,睡一觉明天就想通一点点,后天又解决一点点……

facebook实现一个react的MVVM框架,炒作一个叫反应式编程的概念。其实它的核心就是knockout的弱化版。对我看来,用数学的自变量,因变量来表达它们之间的关系更适合。其中绑定属性,监控数组的方法就是自变量,这是由用户直接操作的。计算属性,求值函数,视图刷新函数就是因变量,由下层的绑定属性,数组方法所驱动。0.99起,开始大量性能优化,把求值函数,视图刷新函数都共享了。但这些东西,用户根本不需要知道,说不定某天发现更高效的实现方式,它们就不存在了。所有要注意之处,在《入门教程》已经标明。要深入可以看《最佳实践》。再者看源码,这些概念只是辅助你看当前版本的源码。想成为高手,还是从源码着手。只是想快速完成任务,看我的《入门教程》就够了。

感谢这个时代,正因为有了IE6才有我们前端,正因为有前端才有我们这些民科外行沾光IT的福利。

迷你MVVM框架在github的仓库https://github.com/RubyLouvre/avalon

官网地址http://rubylouvre.github.io/mvvm/

有关avalon的最佳实践或注意点请看这里, 这个我每次发布新版本都可能在这里加东西


朋友们用avalon做的东西

未来avalon的发展方向就是三大重型UI组件:树,GRID,多级菜单。望大家也多多贡献,一起完善这个生态圈。

如果您觉得这文章对您有帮助,可以打赏点钱给我,鼓励我继续写博,我的支付宝

 
 
 
标签: javascriptavalon

avalon1.0正式发布的更多相关文章

  1. 2013年最后的收成:avalon1.0正式发布

    大半年前我就说过,MVVM是前端究极的解决方案,因此之后我大多数时间都在折腾avalon,成立了专门的QQ群与感兴趣的一起讨论.感谢第一批吃螃蟹的人,avalon发展得很快,GITHUB上的贡献人数达 ...

  2. AppBox_v2.0完整版免费下载,暨AppBox_v3.0正式发布!

    文章更新: AppBox v6.0中实现子页面和父页面的复杂交互 AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. AppBox ...

  3. Socket.IO 1.0 正式发布,快速可靠的实时引擎

    Socket.IO 是目前 Web 领域最火的实时引擎,用于实现基于事件的双向实时的通信.它适用于任何平台,浏览器或设备,专注于可靠性和速度.您可以将数据推送到客户端,并获得实时的计数,日志或图表. ...

  4. Django 1.6.0 正式发布,大幅改进事务处理

    Django 1.6.0 正式发布了,查看官方发行说明. 下载地址:Django-1.6.tar.gz ,也可通过 pip 安装: pip install Django==1.6 要求 Python ...

  5. Apache Spark2.0正式发布

    Apache Spark2.0正式发布 7月26日起Databricks开始提供Apache Spark 2.0的下载,这个版本是基于社区在过去两年的经验总结而成,不但加入了用户喜爱的功能,也修复了之 ...

  6. 【G-BLASTN 1.0正式发布】

    [G-BLASTN 1.0正式发布]G-BLASTN使用GPU来加速NCBI-BLAST里的BLASTN模块,单块GTX780比四核CPU平均快6倍. http://www.comp.hkbu.edu ...

  7. Angular4.0.0正式发布,附新特性及升级指南

    本文首发地址:Angular4.0.0正式发布,附新特性及升级指南 作者|孙薇 编辑|尾尾 经历了6个RC版本之后,Angular项目组终于发布了新版,即正式版 Angular 4.0.0.新版的 A ...

  8. 重磅:Spring Boot 2.0 正式发布!

    Spring Boot 2.0 正式发布! 2018/03/01最新消息,传得沸沸扬扬的Spring Boot 2.0 正式发布了. 小编去看了下Spring Boot的官网,正式版本已经释放出来了! ...

  9. Spring Boot 2.0正式发布,新特性解读

    作者|翟永超 Spring Boot 2.0 来啦,有哪些新特性?升级吗? 写在前面 北京时间 3 月 1 日,经过漫长的等待之后,Spring Boot 2.0 正式发布.作为 Spring 生态中 ...

随机推荐

  1. hdu 3460 Ancient Printer

    Problem Description The contest is beginning! While preparing the contest, iSea wanted to print the ...

  2. 查询出各个学科的前3名的同学信息的Sql

    查找各个学科的成绩前3名的学生信息Sql,有2种方法,一种是利用sql的row_number() over()函数,另一种是用子查询, 表设计如下 如果不考虑各个学科的成绩有并列的情况的话,有如下两种 ...

  3. 【Android接口实现】PhotoView——单点支持/多图像缩放,实现了触摸

    转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 今天给大家介绍的开源项目,是来自Github的PhotoView项目,这个项目的主要功能是实现普通的Imag ...

  4. SSAS系列——【07】多维数据(查询Cube)

    原文:SSAS系列——[07]多维数据(查询Cube) 1.什么是MDX? MDX叫做"多维表达式",是一种查询语言,是一种和SQL类似的查询语言,它基于 XML for Anal ...

  5. cmd 跟踪路由

    cmd   命令   tracert  ip 地址 用 来 跟踪路由

  6. JS 数组array方法push, pop, unshift, shift, slice,splice,contact, join, sort

    Array:数组对象用来在单独的变量名中存储一系列的值   定义数组:         1. var arrayObj = new Array();         2. var arrayObj = ...

  7. javascript如何解析json对javascript如何解析json对象并动态赋值到select列表象并动态赋值到select列表

    原文 javascript如何解析json对象并动态赋值到select列表 JSON(JavaScriptObject Notation)一种简单的数据格式,比xml更轻巧.JSON是JavaScri ...

  8. nexus私服linux搭建问题

    一.最近搭建nexus私服,从官网下载下来总是报503服务器无效,很是无奈,最后在网上找到一个可以用的 收藏起来,这里给大家共享一下 下载地址:http://pan.baidu.com/s/1kT3U ...

  9. Python 3.3 try catch所有的错误Error,不包括Exception。关键在于 sys.exc_info()

    import os; import sys; #---------------------------------------------- def main( ) : try : a = 1 / 0 ...

  10. SQL点滴9—SQL Server中的事务处理以及SSIS中的内建事务

    原文:SQL点滴9-SQL Server中的事务处理以及SSIS中的内建事务 我们可以把SSIS中的整个package包含在一个事务中,但是如果在package的执行过程中有一个表需要锁定应该怎么处理 ...