什么是scope
官方文档的解释:
scope is an object that refers to the application model. It is an execution context for expressions. Scopes are arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can watch expressions and propagate events.
Scopes can be nested to limit access to the properties of application components while providing access to shared model properties. Nested scopes are either "child scopes" or "isolate scopes". A "child scope" (prototypically) inherits properties from its parent scope. An "isolate scope" does not. See isolated scopes for more information.
Scopes provide context against which expressions are evaluated. For example {{username}} expression is meaningless, unless it is evaluated against a specific scope which defines the username property.
scope是一个指向应用model的object,也是表达式的执行上下文。
scope被放置于一个类似应用的DOM结构的层次结构中。
什么是Scope characteristics
官方文档的解释:
Scopes provide APIs ($watch) to observe model mutations.
Scopes provide APIs ($apply) to propagate any model changes through the system into the view from outside of the "Angular realm" (controllers, services, Angular event handlers).
示例程序:
<body>
<div ng-app="">
<div ng-controller="firstController">
{{date}}
</div>
</div>
<script type="text/javascript" src="app/index.js"></script>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
</body>
</html>
JS文件:
var firstController;
firstController = function ($scope) {
$scope.date = new Date();
setInterval(function(){
$scope.date= new Date();
},1000)
}
此时,在JS文件中写明了希望时间一秒钟变化一次。但是此时对应的html文件里是不会变化的。所以VIEW中不会发生改变。
model里面改变了,怎么取通知view也去update呢?
angular怎么样才能知道变量发生了改变
要知道变量是否改变,方法不外乎两种
- 能通过固定的接口才能改变变量的值。比如说只能通过set()设置变量的值,set被调用时比较一下就知道了(这种方法写法繁琐)。
- 脏检查(dirty check),将原对象复制一份快照,在某个时间,比较现在对象与快照的值,如果不一样就表明发生变化,这个策略要保留两份变量,而且要遍历对象,比较每个属性,这样就会有性能问题。
Angular的实现是使用脏检查
- angular的策略
-
- 不会脏检查所有的对象,当对象被绑定到html中(比如实例程序的date对象),这个对象添加为检查对象(watcher)。
- 不会脏检查所有的属性,同样当属性被绑定后,这个属性会被列为检查的属性
- 在angular程序初始化时,会将绑定的对象的属性添加为监听对象(watcher),也就是说一个对象绑定了N个属性,就会添加N个watcher。
什么时候执行脏检查
angular所系统的方法中都会触发比较事件,比如:controller初始化的时候,所有以ng-开头的事件执行后,都会触发脏检查。
实例中的代码,此时时间一秒钟发生一次改变(也确实是改变了,但是没有触发脏检查。所以不会触发view上的对象去改变)
setInterval(function(){
$scope.date= new Date();
},1000)
手动触发脏检查
$apply仅仅只是进入angular context,然后通过$digest去触发脏检查
setInterval(function(){$scope.$apply(function(){$scope.date= new Date();})},1000)
$apply如果不给参数的话,会检查改$scope里所有的监听的属性,推荐给上参数
$digest()
- 所属的scope和其所有子scope的脏检查,脏检查又会触发$watch(),整个angular双向绑定机制就活了起来
- 不建议直接调用$digest(),而应该使用$apply,$apply其实不能把信直接送给$digest, 之间还有$eval门卫把关,如果$apply带的表达方式不合法,$eval会把错误送交$exceptionHandler,合法才触发digest,所以更安全