在AngularJS中,范围隔离概念究竟如何运作?这是我的推理正确吗?

时间:2015-11-15 18:05:10

标签: javascript angularjs angularjs-directive angularjs-scope javascript-framework

我在AngularJS中绝对是新的,我正在研究它。我对一个展示如何使用隔离范围概念的示例有一些疑问。

所以提供的示例是包含此 app.js 文件的单页面应用程序,其中包含所有应用程序逻辑:

var myApp = angular.module('myApp', ['ngRoute']);

myApp.config(function ($routeProvider) {

    $routeProvider

    .when('/', {
        templateUrl: 'pages/main.html',
        controller: 'mainController'
    })

    .when('/second', {
        templateUrl: 'pages/second.html',
        controller: 'secondController'
    })

    .when('/second/:num', {
        templateUrl: 'pages/second.html',
        controller: 'secondController'
    })

});

myApp.controller('mainController', ['$scope', '$log', function($scope, $log) {

    $scope.person = {
        name: 'John Doe',
        address: '555 Main St., New York, NY 11111'
    }

}]);

myApp.controller('secondController', ['$scope', '$log', '$routeParams', function($scope, $log, $routeParams) {



}]);


/* Declare a directive named "searchResult" */
myApp.directive("searchResult", function() {
   return {
       restrict: 'AECM',                                // This represent the ways to declare the directive into my code
       templateUrl: 'directives/searchresult.html',     // This is the template page that implement the directive
       replace: true,                                   // This specify that the directive in the main HTML code is replaced by the template code

       /* This isolate the directive scope (the model of the directive) from its parent scope (the controller that handle the page in which
        the directive is used). Because I can't directly use the person.name and the person.address property declared in the parent scope I
        specify that I use the person-name and the person-address passed as custom attribute of the search-result directive where it is used (in         the main.html)
       */
       scope: {
           personName: "@",
           personAddress: "@"
       }
   }
});

这是使用搜索结果指令的 main.html 页面:

搜索

<h3>Search Results</h3>
<div class="list-group">
    <search-result person-name="{{ person.name }}" person-address="{{ person.address }}"></search-result>
</div>

这是 searchResult.html 的代码,它是我的指令的模板:

<a href="#" class="list-group-item">
    <h4 class="list-group-item-heading">{{ personName }}</h4>
    <p class="list-group-item-text">
        {{ personAddress }}
    </p>
</a>

所以,根据我的理解(但如果我做错了断言,请纠正我)范围隔离以下列方式工作:

为避免出现问题,我可以通过父作用域(例如主页的控制器)隔离子指令的作用域。

为此,我只需在指令JavaScript声明中插入范围 JSON对象:

scope: {
    .............
    .............
    .............
}

但是现在从我的指令中我不能再直接访问父作用域(控制器作用域)中声明的名称地址属性。

因此,如果我必须使用这些值,我将以这种方式声明隔离的指令范围对象:

scope: {
    personName: "@",
    personAddress: "@"
}

表示 personName 属性在搜索结果中声明了人名文本值 HTML声明(以及 personAddress 的dame事实,实际上我的 main.hml 文件

<search-result person-name="{{ person.name }}" person-address="{{ person.address }}"></search-result>

从这里我可以直接访问 person.name person.address ,因为我在这里使用控制器范围 (父范围)

现在,在我的JavaScript指令中,我将这些值获取到隔离的子作用域对象的 personName personAddress 属性中,并在我的指令模板中访问这些属性,这样:

<a href="#" class="list-group-item">
    <h4 class="list-group-item-heading">{{ personName }}</h4>
    <p class="list-group-item-text">
        {{ personAddress }}
    </p>
</a>

我的推理是正确还是我错过了什么?

4 个答案:

答案 0 :(得分:1)

这是对的。在指令上使用隔离范围使其可以在新的上下文中使用,而不会有污染其父范围的危险。

答案 1 :(得分:1)

@属性字符串绑定 =双向模型绑定 &安培;回调方法绑定

更深入理解指令的范围

enter link description here

答案 2 :(得分:1)

您的理解是正确的。隔离范围与正常范围的不同之处在于它不会从其父范围原型继承。这在创建可重用组件时非常有用,这些组件不应该意外地读取或修改父范围中的数据,并且它也不会与父范围强烈耦合。

要扩展通过隔离范围可用的内容,您可以使用三种选项(来自documentation):

  

@或@attr - 将本地范围属性绑定到DOM的值   属性。由于DOM属性,结果总是一个字符串   字符串。如果未指定attr名称,则属性名称为   假设与本地名称相同。范围的给定和小部件定义:{localName:&#39; @ myAttr&#39; },   那么widget作用域属性localName将反映插值   hello {{name}}的值。由于名称属性发生了变化,因此   小部件范围上的localName属性。该名称是从   父范围(不是组件范围)。

     

=或= attr - 设置本地范围属性与通过值定义的名称的父范围属性之间的双向绑定   oftr属性。如果未指定attr名称,则为该属性   假定name与本地名称相同。给定范围的小部件定义:{   localModel:&#39; = myAttr&#39;然后,widget作用域属性localModel将   反映父范围内parentModel的值。任何改变   parentModel将反映在localModel和任何更改中   localModel将反映在parentModel中。如果是父范围属性   它不存在,它会抛出一个NON_ASSIGNABLE_MODEL_EXPRESSION   例外。你可以使用=?避免这种行为?或=?attr以便   将该属性标记为可选。如果你想浅薄的   更改(即$ watchCollection而不是$ watch)你可以使用= *或   = attr(= ?或= *?attr,如果属性是可选的)。

     

<强>&安培;或&amp; attr - 提供了一种在上下文中执行表达式的方法   父范围。如果未指定attr名称,则为属性名称   假定与本地名称相同。给定范围的小部件定义:{   localFn:&#39;&安培; myAttr&#39;然后隔离范围属性localFn将指向   count = count + value表达式的函数包装器。经常   希望通过表达式从隔离范围传递数据   在父范围内,可以通过传递本地地图来完成   变量名和值到表达式包装器fn中。例如,   如果表达式是增量(金额),那么我们可以指定金额   通过将localFn调用为localFn({amount:22})来获取值。

答案 3 :(得分:1)

我已经解释了范围隔离的工作原理以及与rootScope相对应的另一个问题

$scope and $rootscope confusion

如果有这个帮助,请告诉我