相关链接
Avalon github地址
Avalon 快速入门
基于 Avalon的组件库-OniUI
Avalon 入门教程
Avalon CDN
简介
Avalon
是司徒正美开发和维护的一款基于虚拟DOM
与属性劫持的迷你、 易用、 高性能 的 前端MVVM
框架,最早发布于2012.09.15。 其拥有超优秀的兼容性,支持移动开发、后端渲染、WEB Component
式组件开发,无需编译,开箱即用,可以轻松实现数据的隔离和双向绑定。
优点
- 使用简单,在
HTML
中添加绑定,在JS
中用avalon.define
定义ViewModel
,再调用avalon.scan
方法,就可以了; - 体积小巧,没有任何依赖,压缩后仅有60多kb;
- 兼容
IE6+
; - 效率更高,跑起来比
angular
和knockout
都要更快,在移动端上该优势会更大(avalon
有移动端专版的avalon.modern.js
); - 有配套的
UI
库; - 支持管道符风格的过滤函数,方便格式化输出;
- 局部刷新的颗粒度已细化到一个文本节点,特性节点;
- 它将要操作的节点,在第一次扫描就与视图刷新函数相绑定,并缓存起来,避免了选择器的出场的,大量减少了
DOM
操作; - 使用类似
CSS
的重叠覆盖机制,让各个ViewModel
分区交替地渲染页面; DOM
节点移除时,智能卸载对应的视图刷新函数,节约内存;- 操作数据即操作
DOM
,对ViewModel
的操作都会同步到View
与Model
; - 实现了数据和视图的隔离,可维护性好。
MVVM模式
Avalon
将所有前端代码彻底分成两部分,视图的处理通过绑定实现, 业务逻辑则集中在一个个叫vm
的对象中处理;操作vm
的数据,就自然而然地同步到视图。Object.defineProperty
的作用是将对象的某一个属性,转换一个setter
与getter
, 只要劫持这两个方法,通过Pub/Sub
模式就能偷偷操作视图。
Avalon
也是基于这个理论建立起来的,在视图上添加一些标记,然后在Java
中对对象的属性进行监听,当这些属性发生变化,以观察者模式,通知视图进行变更;视图上也可以绑定一些事件,然后当这些事件被触发时,反过来修改这个对象的特定属性,这叫双向绑定。所有需要操作的数据被集中一起管理,它们合并成一个叫
ViewModel
的东西,而原来的HTML
页面只做了一些修改,称之为View
,而View
本身是一个动态模板(Live Template)
。
使用
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Avalon demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="./avalon.js"></script>
<script type="text/javascript">
var vm = avalon.define({ // wrap 用作该 Model的载体
$id: "maincontainer", // 告诉avalon这个Model是作用于哪个ms-controller的
msg: "Hello,world!", // 定义一个avalon对象属性“msg”,其值是“Hello,world!”
desc: "This is description!"
});
avalon.scan(); // 这句话可以加,也可以不加,因为avalon有自己的DOMReady模块,会自动扫描全文。
</script>
<style>
.ms-controller {
display: none;
}
</style>
</head>
<body>
<div>
<!-- 给div加上监听器 -->
<div ms-controller="maincontainer">
<p>{{msg}}</p>
<p>{{@desc}}</p>
</div>
</div>
</body>
</html>
以上代码的执行流程如下:
1)将 avalon.js
引入页面中;
2)设置控制域,为视图 html
指定一个控制域,并绑定一个容器(avalon
称之为 vm
);
3)使用 avalon.define({})
定义一个 vm
实例,$id
对应控制域名,告诉 avalon
这个实例属于哪个控制域;
4)将 vm
中的数据(实例中的 msg、desc
等)绑定到视图中,可以使用 {{@*}}
或者指令(不过,低版本的 avalon
使用{{}}
可能会导致某种 bug
。)
相关概念
控制域
<div ms-controller="maincontainer">
如上所示,Avalon
的控制域属性名为 “ms-controller”
,把它绑定到一个容器后,Avalon
就能扫描和监听这个容器内的所有(绑定了 Avalon
方法或带有插值表达式的)元素了。
定义 Model
Model
的定义是通过 javascript
来实现的,通过 avalon.define()
函数来定义,如下:
<script>
var model = avalon.define('maincontainer', function(vm){
vm.msg= 'Hello,world!';
});
</script>
或者:
<script type="text/javascript">
var vm = avalon.define({ // wrap 用作该 Model的载体
$id: "maincontainer", // 告诉avalon这个Model是作用于哪个ms-controller的
msg: "Hello,world!", // 定义一个avalon对象属性“msg”,其值是“Hello,world!”
desc: "This is description!"
});
avalon.scan(); // 这句话可以加,也可以不加,因为avalon有自己的DOMReady模块,会自动扫描全文。
</script>
Avalon
的所有操作都是围绕 vm
进行。 vm
,亦即view model
,视图模型。将一个 JS
对象添加一个 $id
属性, 再放到 avalon.define
方法里面,就能得到一个 vm
。
vm
是一种利用 Proxy
或 Object.defineProperties
或VBScript
创建的特殊对象。
- 在
avalon
中,使用avalon.define({ ... })
的形式来定义一个Model
实例(其参数可以看做一个avalon
数据对象); $id
是内置属性,对应所要扫描和监控的控制域名,这个id
会找到html
页面的对应的controller
;Model
实例内部定义了一个属性msg
,在对应的控制域里,使用avalon
插值表达式{{msg}}
,可以自动绑定其值:Hello,world!
。
以上实例页面效果如下: