AngularJS开发指南9:AngularJS作用域的详解

AngularJS作用域是一个指向应用模型的对象。它是表达式的执行环境。作用域有层次结构,这个层次和相应的DOM几乎是一样的。作用域能监控表达式和传递事件。

作用域的特点

作用域提供APIs($watch)来观察模型的变化。

作用域提供APIs($apply)将任何模型的改变,反映到视图上。

作用域能通过共享模型成员的方式嵌套到应用组件上。一个作用域从父作用域继承属性。

作用域提供表达式执行的上下文。比如说表达式{{username}}本身是无意义的,除非把它放到指定username属性的作用域中。

作为数据模型的作用域

作用域是控制器和视图之间的“胶水”。在模板链接阶段,指令设置好作用域的$watch表达式。$watch使得指令能知晓属性的改变,这使得指令能重新渲染和更新DOM中的值。

控制器和指令都持有作用域的引用,但是不持有对方的引用。这使得控制器能从指令和DOM中脱离出来。这很重要,因为这使得控制器完全不需要知道view的存在,这大大改善了应用的测试。

举个例子:

<!doctype html> <html ng-app> <head> <script src="https://code.angularjs.org/angular-1.0.2.min.js"></script> <script src="https://www.linuxidc.com/script.js"></script> </head> <body> <div ng-controller="MyController"> Your name: <input type="text" ng-model="username"> <button ng-click='sayHello()'>greet</button> <hr> {{greeting}} </div> </body> </html>

 

script.js:

function MyController($scope) { $scope.username = 'World'; $scope.sayHello = function() { $scope.greeting = 'Hello ' + $scope.username + '!'; }; }

 

上例中MyController将值World赋给了作用域中的username。然后作用域将这个赋值的操作通知给input,然后input就会被渲染成预填充了值的样子。这展示控制器如何将数据写入到作用域。

同样的,控制器能将行为添加到作用域,正如你看到的sayHello方法,这个方法是在用户点击'greet'按钮时被调用的。

逻辑上来说,表达式{{greeting}}的渲染需要:

获取模板中定义了{{greeting}}DOM节点相关的作用域。在这个例子里,就是传入到MyController的作用域。

结合上一步获取到的作用域来计算表达式的值,将该值在DOM中替换掉表达式。

你可以把作用域和它的属性当做是用来渲染视图的数据。作用域是视图唯一相关联的变化来源。

作用域层级

每一个AngularJS应用都有一个绝对的根作用域。但是可能有多个子作用域。

一个应用可以有多个作用域,因为有一些指令会生成新的子作用域(参考指令的文档看看哪些指令会创建新作用域)。当新作用域被创建的时候,他们会被当成子作用域添加到父作用域下,这使得作用域会变成一个和相应DOM结构一个的树状结构。

当AngularJS执行表达式{{username}},它会首先查找和当前节点相关的作用域中叫做username的属性。如果没找到,那就会继续向上层作用域搜索,直到根作用域。在Javascript中,这被称为原型类型的继承,子作用域以原型的形式继承自父作用域。

下面这个例子展示了应用中的作用域,它们的继承关系。

<!doctype html> <html ng-app> <head> <script src="https://code.angularjs.org/angular-1.0.2.min.js"></script> <script src="https://www.linuxidc.com/script.js"></script>
  <style>
    .doc-example-live .ng-scope {       border: 1px dashed red;     }   </style> </head> <body> <div ng-controller="EmployeeController"> Manager: {{employee.name}} [ {{department}} ]<br> Reports: <ul> <li ng-repeat="employee in employee.reports"> {{employee.name}} [ {{department}} ] </li> </ul> <hr> {{greeting}} </div> </body> </html>

script.js:

 

function EmployeeController($scope) { $scope.department = 'Engineering'; $scope.employee = { name: 'Joe the Manager', reports: [ {name: 'John Smith'}, {name: 'Mary Run'} ] }; }

 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/fc73cc9a0a706e3244eddda3b511e24f.html