大部分传统的模板系统,对模板的渲染是个线性单向的过程;模板或变量与模板混合在一起产生结果的标记集合。任何对模型的改变都需要通过模板的重新计算。但AngularJS有所不同,任何用户引发的视图的改变,都会映射在模型上,继而任何模型的改变,也会立即传播到整个模板。
一、作用域
AngularJS中的$scope对象是模板的域模型(domain model),也称为作用域实例(instance)。通过对其赋值,可以传递数据给模板渲染。
每个$scope都是Scope类的实例。Scope类有很多方法,用于控制作用域的生命周期、提供事件传播(event-progagation)功能,以及支持模板的渲染等。
1.1 作用域层级
ng-controller指令是作用域创建(scope-creating)指令。当在DOM树中遇到作用域创建指令时,AngularJS都会创建Scope类的新实例$scope。新创建的作用域实例$scope会拥有$parent属性,并指向它的父作用域。
AngularJS拥有$routScope,它是其他所有作用域的父作用域,将在新应用启动时创建。众多作用域形成了以$rootScope为根的树结构。
1.2 作用域层级和继承
作用域中定义的属性对所有子作用域是可见的,只要子作用域没有定义同名的属性。
AngularJS中的作用域继承和Javascript中的原型继承遵循同样的规则,沿继承树向上查找属性,直至找到为止。
1.3 在作用域层级中继承的风险
有两种方法可以从子作用域中影响定义在父作用域中的属性:
首先,可以使用$parent属性明确地引用父作用域。但这种解决方案相当不可靠。
另一种解决方案是将变量绑定为某对象的属性,而不是直接绑定为作用域的属性。
<body ng-app ng-init="thing={name:'World'}"> <h1>Hello,{{thing.name}}<h1> <div ng-controller="HelloCtrl"> Say hello to:<input type="text" ng=model="thing.name"> <h2>Hello,{{thing.name}}!</h2> </div> </body>
1.4 作用域生命周期
作用域提供独立的命名空间,避免变量的命名冲突。因此,小型、组织良好的作用域,能节约内存的使用。作用域在不需要后会被销毁,在其中暴露的模型和函数都会被垃圾回收。
二、控制器
控制器的主要职责是初始化作用域实例。
2.1 提供模型的初始值。
2.2 增加UI相关的行为(函数)以扩展$scope对象。
控制器可以让你在JavaScript代码中表达初始化逻辑,而不是污染HTML模板。
三、模型
AngularJS的模型(model)实际上就是普通的JavaScript对象。与控制器类似,不需要特别地去扩展任何AngularJS底层类,也不用去构造模型对象。
四、视图
AngularJS与HTML和DOM有着更加紧密的联系,因为AngularJS依靠浏览器去解析模板文本,浏览器将文本转换成DOM树之后,AngularJS参与进来,开始遍历解析好的DOM结构。当遇到指令时,AngularJS就执行相关逻辑,将指令转换成页面的动态部分。