报名截止 | 班级类型 | 报名情况 |
03月12日 | 就业金领班 | 已满 |
03月05日 | 强化技能班 | 爆满 |
02月25日 | 名企就业班 | 热招中 |
02月25日 | 在职转行班 | 热招中 |
02月20日 | 待业提升班 | 爆满 |
发布时间:2016年03月23日
在开始之前,我们看一下静态模板是怎么工作的:
我之前写了一个叫ejs的静态模板引擎:
[html] view plaincopyprint?
1. <script type="tmpl" id="table_tmpl">
2. <&= title() &>
3. <table border=1>
4. <&- for(var i=0,tl = @trs.length,tr;i<tl;i++){ -&>
5. <&- tr = @trs[i]; -&>
6. <tr>
7. <td><&= tr.name;; &></td> <td><&= tr.age; &></td> <td><&= tr.sex || "男" &></td>
8. </tr>
9. <& } &>
10. </table>
11. <&# 怎么可能不支持图片 &>
12. <img src="<&= @href &>">
13. </script>
14.
它是以一个script标签做容器,里面的整个叫模板。模板里面有许多以 <& 与 &>划分出来的区块,用于插入JS代码,以@开头的变量是对应于数据包中的某个属性。
几乎所有静态模板的实现原理都是一样的,将这个模板变成一个函数,然后里面分成静态部分与动态部分,静态部分就是上面的HTML部分,转换为一个个字符串,动态部分就是插入的JS代码, 它们基本上原封不动地成为函数体的逻辑。然后我们传入一个对象给这个函数,最后得到一个符合HTML格式的字符串,最后用它贴到页面上某个位置就行了。
静态模板有几个缺点,首先它容易混入大量的JS逻辑,对于菜鸟来说,他们特别喜欢在里面放入越来越多JS代码。这个在JSP年代,已经证明是bad practice。为此出现了logic-less的 mustache。 其次,它更新视图总是一大片一大片地处理,改动太大。最后,是由于第2点引发的问题,它对事件绑定等不友好,因为一更新,原来的节点都被消灭了,需要重新绑定。幸好,jQuery普及了事件代理,这问题才没有 暴露出来。
再看动态模板,几乎所有MVVM框架都用动态模板(当然也有例外,如emberjs)。动态模板以整个DOM树为容器,它通过扫描方式进行第一次更新视图。 在静态模板,通过<& 与 &>划分的部分,转换为绑定属性与{{}}插值表达式(这是一种文本绑定,在avalon中,我们可以通过|html过滤器,转换html绑定) 这样就有效阻止用户在页面上写逻辑。虽然动态模板也支持ms-if, ms-each等表示逻辑关系的绑定,但它的值最复杂也只能是一个表达式。 在绑定属性中,属性名用于指定操作行为,如切换类名,控制显示,循环渲染,绑定事件,数据填充什么的,而属性值是决定这些操作是否执行,与渲染结果。 由于双向绑定的关系,它不像静态模板那样,每次都要自己将数据包放进函数,得到结果,然后innerHTML刷新某个区域。它是在用户为VM的某个属性进行重新赋值,将视图中对应的某个文本节点, 特性节点或元素节点的值进行重刷。因此不会影响事件绑定。
在avalon中,这些视图刷新函数都有个element属性,保持对应的元素节点,每次同步时,都会检测此元素节点是否在DOM树,不在DOM树就取消订阅此刷新函数,节约内存,防止无效操作。
因此,你们可以看区别了吧。绑定属性与插值表达式就是对应静态模板中的JS逻辑部分,由于只允许为表达式或单个属性值,复杂度被控制了,强制用户将它们转移到VM中。 VM作为一个数据源,对应静态模板的数据包,并且多了一个自动触发功能,进化成一个消息中心。
[html] view plaincopyprint?
1. <p ms-controller="test" ms-click="click">{{ a }}</p>
2.
3. <script>
4. avalon.define("test", function(vm) {
5. vm.a = '123';
6. vm.click = function() {
7. vm.a = new Date - 0
8. }
9. })
10. </script>
最后要注意的是,HTML5已经规定,特性节点的名字只能小写,因此什么ms-ui-xxx, 都要小写化!这是浏览器行为,无可奈何。