angularjs
自动初始化
Angular 在以下两种情况下自动初始化,一个是在 DOMContentLoaded
事件触发时,或者在 angular.js
脚本被执行的同时如果 document.readyState
被置为 'complete'
的话。初始化时,Angular 会去找 ng-app
这个指明应用开始所在的指令。如果 ng-app
指令被找到的话,Angular 会做以下几件事:
- 加载
ng-app
指令所指定的 模块 - 创建应用所需的
injector
- 以
ng-app
所在的节点为根节点,开始遍历并编译DOM树(ng-app
指出了应用的哪一部份开始时 Angular 去编译的)
编译器
编译器是 Angular 提供的一项服务,用来遍历DOM节点,查找特定的属性。编译过程分为两个阶段:
- 编译:遍历DOM节点,收集所有的指令,返回一个连接函数(link func)
- 连接:将上一步收集到的每个指令与其所在的作用域(scope)连接生成一个实时视图。任何作用域中的模型改变都会实时在视图中反映出来,同时任何用户与视图的交互则会映射到作用域的模型中。这样,作用域中的数据模型就成了唯一的数据源。
理解视图
绝大多数模板引擎系统采用的是把字符串模板和数据拼接,然后输出一个新的字符串,在前端这个新的字符串作为元素的 innerHTML
属性的值。
这就意味着数据中的任何改变需要重新和模板合并,然后再赋给DOM元素的
innerHTML
属性。这里我们可以看到这种策略的一些问题:
- 读取用户输入及将其与数据合并
- 重写用户输入
- 管理整个更新流程
- 缺少行为表现
Angular 则不同。它的编译器直接使用DOM作为模板而不是用字符串模板。编译阶段的返回结果是一个连接函数(link func),在连接阶段会和特定的作用域中的数据模型连接生成一个 实时的视图
。视图和作用域数据模型的绑定是透明的。开发者不需要做任何特别的调用去更新视图。同时,我们不使用 innerHTML
属性,这样也就不会影响用户输入了。而且,Angular 指令不仅可以包含文本绑定,同时也支持行为操作的绑定(译注:此处可能翻译不甚到位)。
HTML 编译可以细分为三个阶段:
-
$compile
遍历DOM节点,匹配指令。如果编译器发现某个元素匹配一个指令,那么这个指令就被添加到指令列表中(该列表与DOM元素对应)。一个元素可能匹配到多个指令(译注:也就是一个元素里面可能有多个指令)。
-
当所有指令都匹配到相应的元素时,编译器按照指令的
priority
属性来排列指令的编译顺序。然后依次执行每个指令的
compile
函数。每个compile
函数有一次更改该指令所对应的DOM模板的机会。然后,每个compile
函数返回一个link
函数。这些函数构成一个“合并的”连接函数,它会调用每个指令返回的link
函数。 -
之后,
$compile
调用第二步返回的连接函数,将模板和对应的作用域连接。而这又会依次调用连接函数中包含的每个指令对应的link
函数,进而在各个DOM元素上注册监听器以及在相应的scope
中设置对应的$watch s
。
编译阶段收集所有的指令并按照优先级排序,之后在连接阶段将特定的作用域
实例与特定的 <li>
实例连接。