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.

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).

  • Scopes can be nested to isolate application components while providing access to shared model properties. A scope (prototypically) inherits properties from its parent scope.

  • 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 as Data-Model

Scope is the glue between application controller and the view. During the template linking phase the directives set up $watch expressions on the scope. The $watch allows the directives to be notified of property changes, which allows the directive to render the updated value to the DOM.

Both controllers and directives have reference to the scope, but not to each other. This arrangement isolates the controller from the directive as well as from DOM. This is an important point since it makes the controllers view agnostic, which greatly improves the testing story of the applications.

Source

 Edit
  1. <!doctype html>
  2. <htmlng-app>
  3. <head>
  4. <scriptsrc="http://code.angularjs.org/angular-1.0.2.min.js"></script>
  5. <scriptsrc="script.js"></script>
  6. </head>
  7. <body>
  8. <divng-controller="MyController">
  9. Your name:
  10. <inputtype="text"ng-model="username">
  11. <buttonng-click='sayHello()'>greet</button>
  12. <hr>
  13. {{greeting}}
  14. </div>
  15. </body>
  16. </html>

Demo

Your name:  greet

Hello World!

In the above example notice that the MyController assigns World to the username property of the scope. The scope then notifies the input of the assignment, which then renders the input with username pre-filled. This demonstrates how a controller can write data into the scope.

Similarly the controller can assign behavior to scope as seen by the sayHello method, which is invoked when the user clicks on the 'greet' button. The sayHello method can read the username property and create a greetingproperty. This demonstrates that the properties on scope update automatically when they are bound to HTML input widgets.

Logically the rendering of {{greeting}} involves:

  • retrieval of the scope associated with DOM node where {{greeting}} is defined in template. In this example this is the same scope as the scope which was passed into MyController. (We will discuss scope hierarchies later.)

  • Evaluate the greeting expression against the scope retrieved above, and assign the result to the text of the enclosing DOM element.

You can think of the scope and its properties as the data which is used to render the view. The scope is the single source-of-truth for all things view related.

From testability, the separation of the controller and the view is desirable, because it allows us to test the behavior without being distracted by the rendering details.

  1. it('should say hello',function(){
  2. var scopeMock ={};
  3. var cntl =newMyController(scopeMock);
  4. // Assert that username is pre-filled
  5. expect(scopeMock.username).toEqual('World');
  6. // Assert that we read new username and greet
  7. scopeMock.username ='angular';
  8. scopeMock.sayHello();
  9. expect(scopeMock.greeting).toEqual('Hello angular!');
  10. });

Scope Hierarchies

Each Angular application has exactly one root scope, but may have several child scopes.

The application can have multiple scopes, because some directives create new child scopes (refer to directive documentation to see which directives create new scopes). When new scopes are created, they are added as children of their parent scope. This creates a tree structure which parallels the DOM where they're attached

When Angular evaluates {{username}}, it first looks at the scope associated with the given element for theusername property. If no such property is found, it searches the parent scope and so on until the root scope is reached. In JavaScript this behavior is known as prototypical inheritance, and child scopes prototypically inherit from their parents.

This example illustrates scopes in application, and prototypical inheritance of properties.

Source

 Edit
  1. <!doctype html>
  2. <htmlng-app>
  3. <head>
  4. <scriptsrc="http://code.angularjs.org/angular-1.0.2.min.js"></script>
  5. <scriptsrc="script.js"></script>
  6. </head>
  7. <body>
  8. <divng-controller="EmployeeController">
  9. Manager: {{employee.name}} [ {{department}} ]<br>
  10. Reports:
  11. <ul>
  12. <ling-repeat="employee in employee.reports">
  13. {{employee.name}} [ {{department}} ]
  14. </li>
  15. </ul>
  16. <hr>
  17. {{greeting}}
  18. </div>
  19. </body>
  20. </html>

Demo

Manager: Joe the Manager [ Engineering ]
Reports:

  • John Smith [ Engineering ]
  • Mary Run [ Engineering ]

Notice that the Angular automatically places ng-scope class on elements where scopes are attached. The <style>definition in this example highlights in red the new scope locations. The child scopes are necessary because the repeater evaluates {{employee.name}} expression, but depending on which scope the expression is evaluated it produces different result. Similarly the evaluation of {{department}} prototypically inherits from root scope, as it is the only place where the department property is defined.

Retrieving Scopes from the DOM.

Scopes are attached to the DOM as $scope data property, and can be retrieved for debugging purposes. (It is unlikely that one would need to retrieve scopes in this way inside the application.) The location where the root scope is attached to the DOM is defined by the location of ng-app directive. Typically ng-app is placed an the <html>element, but it can be placed on other elements as well, if, for example, only a portion of the view needs to be controlled by angular.

To examine the scope in the debugger:

  1. right click on the element of interest in your browser and select 'inspect element'. You should see the browser debugger with the element you clicked on highlighted.

  2. The debugger allows you to access the currently selected element in the console as $0 variable.

  3. To retrieve the associated scope in console execute: angular.element($0).scope()

Scope Events Propagation

Scopes can propagate events in similar fashion to DOM events. The event can be broadcasted to the scope children or emitted to scope parents.

Source

 Edit
  1. <!doctype html>
  2. <htmlng-app>
  3. <head>
  4. <scriptsrc="http://code.angularjs.org/angular-1.0.2.min.js"></script>
  5. <scriptsrc="script.js"></script>
  6. </head>
  7. <body>
  8. <divng-controller="EventController">
  9. Root scope <tt>MyEvent</tt> count: {{count}}
  10. <ul>
  11. <ling-repeat="i in [1]"ng-controller="EventController">
  12. <buttonng-click="$emit('MyEvent')">$emit('MyEvent')</button>
  13. <buttonng-click="$broadcast('MyEvent')">$broadcast('MyEvent')</button>
  14. <br>
  15. Middle scope <tt>MyEvent</tt> count: {{count}}
  16. <ul>
  17. <ling-repeat="item in [1, 2]"ng-controller="EventController">
  18. Leaf scope <tt>MyEvent</tt> count: {{count}}
  19. </li>
  20. </ul>
  21. </li>
  22. </ul>
  23. </div>
  24. </body>
  25. </html>

Demo

Root scope MyEvent count: 0

  • $emit('MyEvent') $broadcast('MyEvent') 
    Middle scope MyEvent count: 0

    • Leaf scope MyEvent count: 0
    • Leaf scope MyEvent count: 0

Scope Life Cycle

The normal flow of browser receiving an event is that it executes a corresponding JavaScript callback. Once the callback completes the browser re-renders the DOM and returns to waiting for more events.

When the browser calls into JavaScript the code executes outside the Angular execution context, which means that Angular is unaware of model modifications. To properly process model modifications the execution has to enter the Angular execution context using the $apply method. Only model modifications which execute inside the $applymethod will be properly accounted for by Angular. For example if a directive listens on DOM events, such as ng-click it must evaluate the expression inside the $apply method.

After evaluating the expression, the $apply method performs a $digest. In the $digest phase the scope examines all of the $watch expressions and compares them with the previous value. This dirty checking is done asynchronously. This means that assignment such as $scope.username="angular" will not immediately cause a $watch to be notified, instead the $watch notification is delayed until the $digest phase. This delay is desirable, since it coalesces multiple model updates into one $watch notification as well as it guarantees that during the $watchnotification no other $watches are running. If a $watch changes the value of the model, it will force additional$digest cycle.

  1. Creation

    The root scope is created during the application bootstrap by the $injector. During template linking, some directives create new child scopes.

  2. Watcher registration

    During template linking directives register watches on the scope. These watches will be used to propagate model values to the DOM.

  3. Model mutation

    For mutations to be properly observed, you should make them only within the scope.$apply(). (Angular APIs do this implicitly, so no extra $apply call is needed when doing synchronous work in controllers, or asynchronous work with $http or $timeout services.

  4. Mutation observation

    At the end $apply, Angular performs a $digest cycle on the root scope, which then propagates throughout all child scopes. During the $digest cycle, all $watched expressions or functions are checked for model mutation and if a mutation is detected, the $watch listener is called.

  5. Scope destruction

    When child scopes are no longer needed, it is the responsibility of the child scope creator to destroy them viascope.$destroy() API. This will stop propagation of $digest calls into the child scope and allow for memory used by the child scope models to be reclaimed by the garbage collector.

Scopes and Directives

During the compilation phase, the compiler matches directives against the DOM template. The directives usually fall into one of two categories:

  • Observing directives, such as double-curly expressions {{expression}}, register listeners using the$watch() method. This type of directive needs to be notified whenever the expression changes so that it can update the view.

  • Listener directives, such as ng-click, register a listener with the DOM. When the DOM listener fires, the directive executes the associated expression and updates the view using the $apply() method.

When an external event (such as a user action, timer or XHR) is received, the associated expression must be applied to the scope through the $apply() method so that all listeners are updated correctly.

Directives that Create Scopes

In most cases, directives and scopes interact but do not create new instances of scope. However, some directives, such as ng-controller and ng-repeat, create new child scopes and attach the child scope to the corresponding DOM element. You can retrieve a scope for any DOM element by using anangular.element(aDomElement).scope() method call.

Controllers and Scopes

Scopes and controllers interact with each other in the following situations:

  • Controllers use scopes to expose controller methods to templates (see ng-controller).

  • Controllers define methods (behavior) that can mutate the model (properties on the scope).

  • Controllers may register watches on the model. These watches execute immediately after the controller behavior executes.

See the ng-controller for more information.

Scope $watch Performance Considerations

Dirty checking the scope for property changes is a common operation in Angular and for this reason the dirty checking function must be efficient. Care should be taken that the dirty checking function does not do any DOM access, as DOM access is orders of magnitude slower then property access on JavaScript object.

 

What are Scopes?的更多相关文章

  1. AnjularJS系列5 —— scopes、module、controller

    第五篇, scopes.module.controller 这一篇,感觉,在前面几篇就使用过的属性,但,总觉得没有理解透彻,有待完善!~ 1.scopes A.定义:$scope是一个把view(一个 ...

  2. Python Scopes and Namespaces

    Before introducing classes, I first have to tell you something about Python's scope rules. Class def ...

  3. 大漠推荐的教程:创建你自己的AngularJS -- 第一部分 Scopes

    创建你自己的AngularJS -- 第一部分 Scopes http://www.html-js.com/article/1863

  4. IdentityServer4之Clients、Scopes、Claims与Token关联

    IdentityServer4之Clients.Scopes.Claims与Token关联 参考 官方文档:client.identity_resource.api_resource:三类配置项介绍描 ...

  5. The confusion about jsp four scopes and ServletContext,HttpSession,HttpServletReqest,PageContext

    The jsp four scopes are same with ServletContext,HttpSession,HttpServletRequest,PageContext? How ser ...

  6. Swinject 源码框架(三):Object Scopes

    Object Scopes 指定了生成的实例在系统中是如何被共享的. 如何指定 scope container.register(Animal.self) { _ in Cat() } .inObje ...

  7. spring作用域(Spring Bean Scopes Example)

    http://docs.spring.io/spring/docs/2.0.x/reference/beans.html#beans-factory-scopes In Spring, bean sc ...

  8. Subnet Pools and Address Scopes

     Why is IPAM important for Neutron? •No VM connectivity without a valid IP assigned •Duplicate subne ...

  9. 【AnjularJS系列5 】— scopes、module、controller

    第五篇, scopes.module.controller 这一篇,感觉,在前面几篇就使用过的属性,但,总觉得没有理解透彻,有待完善!~ 1.scopes A.定义:$scope是一个把view(一个 ...

随机推荐

  1. java完整的代码执行过程 堆栈+方法区

    07\15-面向对象(static关键字-内存图解)

  2. Java并发编程概要

    线程开的越多,则性能越好吗? 未必,影响多线程性能的因素有:上下文切换,竞争/死锁,资源限制等.对于这些因素要均衡考量,才能获得较好的性能. 并发控制/线程间的通信方式 基本的并发控制原语有 vola ...

  3. Java中浮点数能连续精确表示整数的范围

    转自http://blog.csdn.net/seizef/article/details/5571783#ref_1,有删改. 先简单介绍一下浮点数在计算机中的组成,在Java中采用的浮点数表示法是 ...

  4. SQL server基本操作(一)

      --1.create database CREATE DATABASE MyDB GO --2.use database USE MyDB GO --3.create table CREATE T ...

  5. 洛谷 P1195 口袋的天空

    题目背景 小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空. 有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖. 题目描述 给你云朵的个数N,再给你M个关系,表示哪些云朵可以连在 ...

  6. SNRO:Number Range

    业务对象是在一定的编号范围内分配编号的,编号既可以是内部分配也可以是外部分配.对于外部分配,用户输入编号,系统检查这个编号是否被占用.对于内部分配,系统会自动的把编号分配给业务对象.所以内部分配和外部 ...

  7. 【转】使用Memcached提高.NET应用程序的性能

    在应用程序运行的过程中总会有一些经常需要访问并且变化不频繁的数据,如果每次获取这些数据都需要从数据库或者外部文件系统中去读取,性能肯定会受到影响,所以通常的做法就是将这部分数据缓存起来,只要数据没有发 ...

  8. <解说linux下proc文件系统>

    proc文件系统的作用是访问系统内核信息 proc不是一个真实的文件系统,它不占系统的外存空间,只是以文件的形式为用户访问linux内核数据提供接口,因为系统内核总是动态的变化,所以我们所捕捉到的也只 ...

  9. 【Qt】Qt之自定义搜索框【转】

    简述 关于搜索框,大家都经常接触.例如:浏览器搜索.Windows资源管理器搜索等. 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定. 简述 效果 细节分析 Coding 源码下载 效果 ...

  10. eclipse juno版本中没用 ant

    下载了谷歌提供的Android集成开发工具ADT,里面封装了Eclipse,但是很奇怪的是竟然没有Ant插件在里面 标准的Eclipse一般都是内置集成了Ant的. 然后到eclipse的plugin ...