在前端MVVM框架设计及实现(一)中有一个博友提出一个见解:css
“html中使用mvvm徒增开发成本”html
我想这位朋友要表达的意思应该是HTML定义了大量的语法标记,HTML中放入了太多的逻辑,从而增长了复杂度前端
将逻辑放入HTML是一个很差的作法,也不建议这么作,即使从复用的角度来说,由于HTML与代码紧密耦合,要想从新组成一个应用程序很是困难git
固然,在构建一个应用程序时,你也能够不使用框架,但不能否认,使用框架将使得你的开发工做变得更容易github
框架都不是万能的,可是在某一种特定的项目中,用最方便快捷的方式达到一样的目的又何乐而不为呢?数组
指令浏览器
在第一节前端MVVM框架设计及实现(一)中,展现了用最简单的代码实现了一个双向绑定的原理以及运做流程,可是若是是做为框架来讲那是远远不够的,因此咱们须要慢慢的完善每个细节,若是要作到操做数据即操做行为,那么就意味着框架要在内部帮你作一大堆额外的事情,这里面涉及的知识面足够让你跨入一个新的层次ruby
咱们先来初步完善第一个功能点:指令数据结构
若是用过 Angular,那么你就会知道directive 是什么框架
简单点:利用声明式的结构来控制布局与行为
<div id='box' ao-controller="box"> <div ao-css-width="w" ao-click='click' ></div> <p> {{ w }} {{ h }} {{ z }} </p> </div>
如图ao-controller,ao-css-width等等HTML自己是没有这语法结构的,那么如何让你将行为关联到HTML元素或者属性上,甚至能让你创造具备自定义行为的新元素
为了实现这种关联,AngularJS取了一个高大上的名字经过引入HTML编译器抽取这些标示能让浏览器识别新的HTML语法,咋一看很高级仔细一想不就是一个模版引擎么?
模版
此与彼同,此非彼也,一说模版就跑出来一个概念,占位与变量替换,几乎全部静态模板的实现原理都是同样的,将这个模板变成一个函数,而后里面分红静态部分与动态部分,静态部分就是上面的HTNMl部分,转换为一个个字符串,动态部分就是插入的JS代码, 它们基本上原封不动地成为函数体的逻辑。而后咱们传入一个对象给这个函数,最后获得一个符合HTML格式的字符串,最后用它贴到页面上某个位置就好了。
静态模板有几个缺点,首先它容易混入大量的JS逻辑,对于菜鸟来讲,他们特别喜欢在里面放入愈来愈多JS代码。这个在JSP年代,已经证实是bad practice。为此出现了logic-less的 mustache。 其次,它更新视图老是一大片一大片地处理,改动太大。最后,是因为第2点引起的问题,它对事件绑定等不友好,由于一更新,原来的节点都被消灭了,须要从新绑定。幸亏,jQuery普及了事件代理,这问题才没有 暴露出来。
再次,字符串模块没有对样式的操做,流程的操做进行封装,没有计算属性,监控数组的东西,很容易诱导用户在页面上写大量业务逻辑,致使代码没法维护。
MVVM引入一种叫DOM模块,像knockout, avalon, angular就是用它们实现双向绑定了,可维护性更高
可见
绑定属性与插值表达式就是对应静态模板中的JS逻辑部分,因为只容许为表达式或单个属性值,复杂度被控制了,强制用户将它们转移到VM中。 VM做为一个数据源,对应静态模板的数据包,而且多了一个自动触发功能,进化成一个消息中心。
实现细节
avalon经过scan执行dom的扫描,其实就是经过遍历指定的节点树拿到对应的HTML语法标记
咱们能够经过controller划分做用域,换句话说就是controller为根节点是往内部层层遍历检测每一个元素上的语法标记
值得注意的细节,在IE67下,在循环绑定中,一个节点若是是经过cloneNode获得,自定义属性的specified为false,没法进入里面的分支,
但若是咱们去掉scanAttr中的attr.specified检测,一个元素会有80+个特性节点(由于它不区分固有属性与自定义属性),很容易卡死页面
本章的代码主要是实现简单的HTML指令的解析,涉及到元素节点的attr属性与文本节点的{{}}插值表达式,经过解析对应的语法标记生成指定的数据结构提供给以后使用
GitHub上会同步更新每章的实现,。。。敬请关注~