JavaScript 迷你 MVVM 框架 avalonjs 1.3.7 发布

cheng19840218 · 2014年11月15日 · 最后由 yutian 回复于 2015年01月29日 · 4933 次阅读

avalon是一款基于 Object.definePropertyVBScript 实现属性监控变动的 MVVM 框架,因此性能比基于脏检测的 angular 来得更好,使用方法也比基于属性转函数的 knockout 来得直接便捷。简单易用易上手兼容性好的是其最大的特点。

下面是详细介绍:

  • avalon现在有三个分支:avalon.js 兼容 IE6,及标准浏览器;avalon.modern.js 则只支持 IE10 及其以上版本,及标准浏览器,主流山寨浏览器 (QQ, 猎豹,搜狗,360, 傲游) ;avalon.observe 是用于研究 es6 的新特性,使用 Object.observe 实现的;
  • avalon拥有强大的组件库,现在由去哪儿网前端架构组在维护与升级,这里;首先是三柱臣,想使用路由器,可以用mmRouter,想使用动画,可以用mmAnimate,想使用 AJAX,可以用mmRequest;其是是 OniUI,树组件差不多开发完毕,届时就有一个拥有 2 个 Grid,1 个树,1 个验证插件等总数近 50 个 UI 组件的库了。
  • avalon 的测试比较庞大,放在独立的仓库中——avalon.test

优势

  • 使用简单,在 HTML 中添加绑定,在 JS 中用 avalon.define 定义 ViewModel,再调用 avalon.scan 方法,它就能动了!
  • 兼容到 IE6 (其他 MVVM 框架,KnockoutJS(IE6), AngularJS(IE9), EmberJS(IE8), WinJS(IE9) ),另有 avalon.mobile,它可以更高效地运行于 IE10 等新版本浏览器中
  • 没有任何依赖,不到 5000 行,压缩后不到 50KiB
  • 支持管道符风格的过滤函数,方便格式化输出
  • 局部刷新的颗粒度已细化到一个文本节点,特性节点
  • 要操作的节点,在第一次扫描就与视图刷新函数相绑定,并缓存起来,因此没有选择器出场的余地。
  • 让 DOM 操作的代码近乎绝迹
  • 使用类似 CSS 的重叠覆盖机制,让各个 ViewModel 分区交替地渲染页面
  • 节点移除时,智能卸载对应的视图刷新函数,节约内存
  • 操作数据即操作 DOM,对 ViewModel 的操作都会同步到 View 与 Model 去
  • 自带 AMD 模块加载器,省得与其他加载器进行整合

学习教程

运行 github 中的示例

将项目下载到本地,里面有一个叫 server.exe 的.Net 小型服务器(可以需要安装.Net4.0), 点击它然后打开里面与 index 开头的 HTML 文件,一边看运行效果,一边看源码进行学习。 Alt text

JS 文件的压缩

java -jar compiler.jar --js avalon.js --js_output_file avalon.min.js
java -jar compiler.jar --js avalon.modern.js --js_output_file avalon.modern.min.js

大家也可以在新浪微博第一时间了解它的变更或各种秘笈分享!

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <script src="avalon.js"></script>
        <script>
            avalon.define({
                $id: "test",
                word: "Hello Avalon"
            })
        </script>
    </head>
    <body>
        <div ms-controller="test">
            <h1>{{word}}!!!!!</h1>
        </div>
    </body>
</html>

avalon

<!DOCTYPE html>
<html>
    <head>
        <title>avalon入门</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script src="avalon.js" ></script>
        <script>
            var first = 0;
            var model = avalon.define("test", function(vm) {
                vm.firstName = "司徒"
                vm.lastName = "正美"
                vm.fullName = {//一个包含set或get的对象会被当成PropertyDescriptor,
                    set: function(val) {//里面必须用this指向scope,不能使用scope
                        var array = (val || "").split(" ");
                        this.firstName = array[0] || "";
                        this.lastName = array[1] || "";
                    },
                    get: function() {
                        return this.firstName + " " + this.lastName;
                    }
                }
                vm.arr = ["aaa", 'bbb', "ccc", "ddd"]
                vm.selected = ["bbb", "ccc"]
                vm.checkAllbool = false
                vm.checkAll = function() {
                    if (!first) {
                        first++
                        return
                    }
                    if (this.checked) {
                        vm.selected = vm.arr
                    } else {
                        vm.selected.clear()
                    }
                }
                vm.checkOne = function() {
                    var bool = this.checked
                    if (!bool) {
                        vm.checkAllbool = false
                    } else {
                        vm.checkAllbool = vm.selected.size() === vm.arr.length
                    }
                }
            })

        </script> 
    </head>
    <body>
        <div ms-controller="test">
            <p>First name: <input ms-duplex="firstName" /></p>
            <p>Last name: <input ms-duplex="lastName"  /></p>
            <p>Hello,    <input ms-duplex="fullName"></p>
            <div>{{firstName +" | "+ lastName }}</div>
            <ul>
                <li><input type="checkbox" ms-duplex-radio="checkAllbool"  data-duplex-changed="checkAll"/>全选</li>
                <li ms-repeat="arr" ><input type="checkbox" ms-value="el" ms-duplex="selected" data-duplex-changed="checkOne"/>{{el}}</li>
            </ul>
        </div>

    </body>
</html>

hello

其绑定属性一览,与 angular, knockout 的指令相很近,学过后两者可以很快上手。 bindings feature

这里还有 TodoMVC 的 avalon 版本学习。

下面是 1.3.7 的更新日志:

  • 【新特征】ms-duplex 绑定全面升级,脱胎换骨,如 avalon.duplexHooks 钩子对象,pipe 内部方法。详看这里的例子
  • 【新特征】添加 data-include-replace 辅助指令 详见这里
  • 【新特征】data-duplex-changed 支持第二个参数 data 详见这里 *【新特征】VM 的$fire 通信机制变成这个样式,all!xxx 是不依赖于 DOM 树向周边 VM 发出通知; up!xxx 与 down!xxx 是依赖于 DOM 向上方或向下方的 VM 发出通知,我们可以 return false 中止广播; 普通的 xxx 只能触发当前的 VM 的$watch 回调。
  • 【新特征】添加 avalon.scanCallback,允许在某次扫描后触发这些回调。详见这里这里的例子 javascript avalon.scanCallback = function(fn, group) { group = group || "$all" var array = scanObject[group] || (scanObject[group] = []) array.push(fn) } avalon.scan = function(elem, vmodel, group) { elem = elem || root group = group || "$all" //.....略 }
  • 【优化】修正 $fire 在跨模块通信时无法通知 widget 组件的 BUG(添加了 createSinalTower 内部方法)
  • 【优化】更改 innerRequire 内部方法的位置,及设置为空函数,方便用户移除“AMD 加载器模块”后也能正常使用
  • 【优化】精简 IE6-8 下 input 事件的模拟
  • 【优化】精简 newSetter 的逻辑 详见这里
  • 【优化】重构 notifySubscribers
  • 【优化】fix getEachProxy BUG 详见这里
  • 【优化】支持生成更多 SVG 元素
  • 【优化】为对付 firefox 插件下严格的语法检测,使用全新的获取全局变量 window 的方法
  • 【优化】修正 ms-src 不能加载 SWF BUG 详见这里
  • 【优化】修正 ms-duplex 绑定 VM 某个子 VM 的属性,input 值修改后没有同步到 vm.$model 的 BUG 详见这里
  • 【优化】修正 avalon.mix 方法拷贝 VBScript 对象时抛错的 BUG 详见这里
  • 【优化】修正 IE6 下因为 for in 循环导致 isPlainObject 不准的 BUG 详见这里
  • 【优化】将 ms-if 去掉的元素都移动 head 标签的 avalon 标签下 详见这里
  • 【优化】让 date 过滤器能像 chrome 那样支持更多日期格式详见这里

本次升级主打的是ms-duplex 2.0,大家可以到这里一窥其强大!ms-duplex2.0 相对于旧的 ms-duplex 只能将 element.value 简单地同步到 VM 中,它添加了自动转换类型的功能(核心库),光标引导(avalon.mask),数据格式化(参看 avalon.mask 的第三个例子,将用户输入内容自动插入千分符),验证机制 (avalon.validation)。

第二大新特性就添加了 avalon.scanCallback 这新方法,允许用户在扫描后进行操作。有了这东西,什么 data-include-rendered, data-repeat-rendered, data-with-rendered 就没有存在的必要了。以后它们内部全部用 avalon.scanCallback 实现。

从 1.3.3 起,我就着手开发静态收集依赖机制,以此为契机,发现许多要改良的地方,全部放到一个叫 avalon.$events.js 的版本上。但经过几个月的研究,发现静态收集依赖,是对压缩不友好的,像 angular 那样需要引入许多奇异的方式来规避这问题。因此我最终放弃这东西,以后改用其他方式提高性能。未来将着力升级三柱臣与 avalon.observe.js。

xxx

朋友们用 avalon 做的东西

期待大家的加入!

顶,非常好用

开始学习中 mark

需要 登录 后方可回复, 如果你还没有账号请 注册新账号