AngularJs学习笔记--Scope

原版地址:http://code.angularjs.org/1.0.2/docs/guide/scope

 

一、什么是Scope

  scopehttp://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope)是一个指向应用modelobject。它也是expressionhttp://www.cnblogs.com/lcllao/archive/2012/09/16/2687162.html)的执行上下文。scope被放置于一个类似应用的DOM结构的层次结构中。scope可以监测(watch,$watchexpression和传播事件。

 

二、scope的特性

  • scope提供$watch APIhttp://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope#$watch),用于监测model的变化。
  • scope提供$apply APIhttp://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope#$apply),在“Angular realm”(controllerserverangular event handler)之外,从系统到视图传播任何model的变化。
  • scope可以在提供到被共享的model属性的访问的时候,被嵌入到独立的应用组件中。scope通过(原型),从parent scope中继承属性。
  • scopeexpression求值之时提供上下文环境。例如,{{username}}表达式是无意义的,除非它与一个特定的定义了”username”属性的scope一起进行求值。

 

三、Scope as Data-Modelscope作为数据模型)

  scope是在应用controllerview之间的纽带。在模版linkinghttp://www.cnblogs.com/lcllao/archive/2012/09/04/2669802.html)的阶段,directivehttp://www.cnblogs.com/lcllao/archive/2012/09/09/2677190.html)在scope中设置$watch表达式。$watchdirective能够得知属性的变化,使得directive将更新后的值渲染到DOM中。

  controllerdirective两者都与scope有引用,但它们两者之间没有(引用)(Both controllers and directives have reference to the scope, but not to each other)。这样的安排,将controllerdirectiveDOM中隔离开来。这是一个重要的地方,因为它让controllerview是隔离的,极大地提升了应用的可测试性(greatly improves the testing story of the applications)。

DOCTYPE HTML>
<html lang="zh-cn" ng-app>
<head>
    <meta charset="UTF-8">
    <title>data-modeltitle>
    <style type="text/css">
        .ng-cloak {
            display: none;
        }
    style>
head>
<body class="ng-cloak">
<div ng-controller="MyController">
    你的名字: <input type="text" ng-model="username"/>
    <button ng-click="sayHello()">欢迎button>
    <hr/>
    {{greeting}}
div>
<script src="../angular-1.0.1.js" type="text/javascript">script>
<script type="text/javascript">
    function MyController($scope) {
        $scope.username = "My Little Dada";
        $scope.sayHello = function() {
            $scope.greeting = "Hello~" + $scope.username + "!";
        };
    }
script>
body>
html>

 

  在上面的例子中我们可以注意到MyController”My Little Dada”对scope中的username属性进行赋值。然后,scope通知input进行赋值,将username的值预先填入input中。这展示了controller如何做才能够写入数据到scope中。

  相似地,controller可以将行为附加在scope中,正如那个当用户点击“欢迎”按钮时触发的sayHello方法一样。sayHello方法可以读取username属性,也可以创建greeting属性。这表明,当它们绑定到HTML input控件时,scope中的属性会自动更新。

  逻辑上,显示{{greeting}}涉及以下两点:

  • 与定义了{{greeting}}表达式的模版DOM节点一起检索scope。在这个例子中,这个scope与传递到MyController中的scope是相同的。(我们在稍后将会讨论scope的层次结构)
  • 通过之前检索的scope,对greeting表达式进行求值,然后将结果作为封闭DOM元素的text的值。

  我们可以认为,scope和它自己的属性可以作为数据,用于渲染视图。scope是所有和view相关的东西单一的真相来源(The scope is the single source-of-truth for all things view related)。

  从可测试性来看,controllerview的分离是值得欣喜的,因为它允许我们在没有渲染细节的干扰下(专注于)测试行为。

   

it('should say hello', function() {
    var scopeMock = {};
    var cntl = new MyController(scopeMock);
   
    // Assert that username is pre-filled
    expect(scopeMock.username).toEqual('World');
    
    // Assert that we read new username and greet
    scopeMock.username = 'angular';
    scopeMock.sayHello();
    expect(scopeMock.greeting).toEqual('Hello angular!');
});

 

四、Scope Hierarchiesscope层次结构)

  每一个angular应用有且只有一个root scope,但可以拥有多个child scope

  应用可以拥有多个child scope,因为一些directive会创建新的child scope(参考directive文档,查看哪些directive可创建新的scope,如ng-repeat)。当新的scope被创建后,他们将作为一个child scope,加入到parent scope中。这样,创建了一个与它们附属的DOM相似的树结构。

  当angular{{username}}求值时,它首先查看与当前元素关联的scopeusername属性。如果没有找到对应的属性,它将会一直向上搜索parent scope,直到到达root scope。在javascript中,这个行为被称为“原型继承”,child scope典型地继承自它们的parent

  这个例子说明应用中的scope(是怎样的),属性的原型继承。

DOCTYPE HTML>
<html lang="zh-cn" ng-app>
<head>
    <meta charset="UTF-8">
    <title>scope-hierarchiestitle>
    <style type="text/css">
        .ng-cloak {
            display: none;
        }
        .ng-scope {
            border: 1px dashed red;
        }
    style>
head>
<body class="ng-cloak">
<div ng-controller="MyController">
    经理:{{employee.name}} [{{department}}] <br/>
    报告:
    <ul>
        <li ng-repeat="employee in employee.reports">
            {{employee.name}} [{{department}}]
        li>
    ul>
    <hr/>
    {{greeting}}
div>
<script src="../angular-1.0.1.js" type="text/javascript">script>
<script type="text/javascript">
    function MyController($scope) {
        $scope.department = "某部";
        $scope.employee = {
            name:"My Little Dada",
            reports: [
                {name:"Lcllao"},
                {name:"那个谁^o^"}
            ]
        };
    }
script>
body>
html>

  注意,angular自动放置ng-scope class到与scope粘附的元素中。