作用域(Scope):控制器和视图之间的粘结剂。
- 是一个存储应用数据模型的对象
- 为 表达式 提供了一个执行上下文
- 作用域的层级结构对应于 DOM 树结构
- 作用域可以监听 表达式 的变化并传播事件
- 是视图渲染的唯一数据来源
作用域中页面渲染时查找取值的顺序
- 在该表达式当前所在的DOM节点所对应的作用域中
- 往上一层的父级作用域中去查找
$rootScope
(相当于全局属性)中查找
说白了就是类似于js的原型继承机制,一级一级向上查找取值,找到了就再不向下查找了,否则继续。
基于作用域的事件传播
- broadcasted :从父级作用域广播至子级 scope
emitted :从子级作用域往上发射到父级作用域(相当于冒泡)
看概念不是很好懂,以下是我根据官网代码改写的一段demo
<!doctype html>
<html ng-app>
<head>
<script src="http://code.angularjs.org/1.2.25/angular.min.js"></script>
</head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
li{
border: 1px solid gray;
}
</style>
<body>
<div ng-controller="EventController">
<tt>父作用域-count:</tt> {{count}}
<ul>
<li ng-repeat="i in [1]" ng-controller="EventController">子作用域-count:{{count}}
<button ng-click="$emit('MyEvent')">$emit('MyEvent')</button>
<button ng-click="$broadcast('MyEvent')">$broadcast('MyEvent')</button>
<br>
<ul>
<li ng-repeat="item in [2]" ng-controller="EventController">
孙作用域-count:{{count}}<tt></tt>
</li>
</ul>
</li>
</ul>
</div>
<script type="text/javascript">
function EventController($scope) {
$scope.count = 0;
$scope.$on('MyEvent', function() {
$scope.count++;
});
}
</script>
</body>
</html>
- 可分别在子作用域中点击触发emit与broadcast
- 触发emit事件时,会在当前作用于执行完后想上冒泡(改变子作用域与父作用域的值)
- 触发broadcast事件时,会在当前作用域执行完后向下传播(改变子作用域与孙作用域的值)
$emit
和$broadcast
在$scope
中内置存在可直接使用
作用域生命周期
- 创建期
root scope
是在应用程序启动时由$injector
创建的。另外,在指令的模版链接阶段(template linking
),指令会创建一些新的子级scope
。 - 注册
$watch
在模版链接阶段(template linking),指令会往作用域中注册 监听器(watch
),而且不止一个。这些 $watch 用来监测数据模型的更新并将更新值传给DOM。 - 数据模型变化
在把数据变化$apply
进来之后,Angular开始进入 $digest 轮循(就是调用$digest()
方法),首先是rootscope
进入$digest
,然后由其把各个监听表达式或是函数的任务传播分配给所有的子级作用域,那样各个作用域就各司其职了,如果监听到自己负责的数据模型有变化,马上就调用$watch
。 - 销毁作用域
- 子级作用域不再需要的时候,这时候创建它们的就会负责把它们回收或是销毁.
- 指令的创建与销毁都可以是隐式也可以是显式的,销毁是通过
scope.$destroy()
。