【问题标题】:Why are my AngularJS directives sharing scope?为什么我的 AngularJS 指令共享范围?
【发布时间】:2013-11-04 18:53:16
【问题描述】:

我尝试制作一个显示名称并允许更改的简单指令。当我在名称页面上放置多个指令时,它们似乎都共享名称属性。我做错了什么?

<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset=utf-8 />
<title></title>

  <script src="http://code.angularjs.org/1.2.0-rc.3/angular.min.js"></script>
  <script src="http://code.angularjs.org/1.2.0-rc.3/angular-resource.min.js"></script>
  <script src="http://code.angularjs.org/1.2.0-rc.3/angular-animate.min.js"></script>
  <script>
    var app = angular.module('app', []);

    app.directive('person', function () {

    function link ($scope, elem, attrs, ctrl) {     

        $scope.name = "OLD"        

        $scope.setName = function() {
            $scope.name = 'NEW';
        }
    }

    return {
      restrict: 'E',
      replace: true,
      template: "<span>Current name = {{name}}<a href='' class='btn' ng-click='setName()'>Change name</a><br></span>",
      link : link,
    }

  });

  app.controller('MainCtrl', function ($scope) { });

  </script>    

</head>

<body ng-controller='MainCtrl'>
  <person></person><br>
  <person></person><br>
  <person></person><br>
  <person></person><br>
</body>

</html>

【问题讨论】:

  • 指令的所有实例共享相同的范围,因为它们不使用独立的范围。签出the directives documentation,“隔离指令的范围”段落

标签: javascript angularjs angularjs-directive


【解决方案1】:

正如前面的回答中提到的,AngularJS 指令的默认行为是共享它们所包含的范围。这种行为通过指令定义对象中的scope 参数进行更改。

您可以在 AngularJS 文档的此部分中查看范围参数的文档:http://docs.angularjs.org/api/ng.$compile#description_comprehensive-directive-api_directive-definition-object

这个参数有三个选项:

  1. scope: false - 共享指令包含的范围的默认行为

  2. scope: true - 为指令创建一个新作用域,其作用类似于其他子作用域,并且原型继承自其父作用域

  3. scope: {} - 创建一个在原型上不从其父范围继承的隔离范围

正如您在 JSBin 示例中看到的那样,选项 2 和 3 都适用于您的示例。区别在于您是否希望新的作用域被隔离。

AngularJS 指南的指令部分有一个很好的部分,说明了为什么隔离作用域可以帮助使用指令创建更好的可重用模块:AngularJS Guide: Isolating the Scope of a Directive

【讨论】:

    【解决方案2】:

    默认情况下,如果您不隔离指令的范围,您将与您的 person 指令的所有实例共享“外部”范围。在您当前的实现中,您每次都需要创建一个不同的控制器才能重用这样的指令。

    但是这个缺陷有一个解决方案,它被称为隔离范围。为此,您可以像这样使用指令的范围选项:

    return {
      restrict: 'E',
      replace: true,
      scope : {}, // this is where the magic happens
      template: "<span>Current name = {{name}}<a href='' class='btn' ng-click='setName()'>Change name</a><br></span>",
      link : link,
    }
    

    你有一个完整的例子和对here部分的解释隔离指令的范围

    【讨论】:

      【解决方案3】:

      默认情况下,指令共享相同的范围。但如果需要,您可以为指令使用 isolated scope:在指令定义中使用 scope: {} 作为字段。

      app.directive('person', function () {
      
          function link ($scope, elem, attrs, ctrl) {     
      
              $scope.name = "OLD"        
      
              $scope.setName = function() {
                  $scope.name = 'NEW';
              }
          }
      
          return {
            restrict: 'E',
            scope: {}
            replace: true,
            template: "<span>Current name = {{name}}<a href='' class='btn' ng-click='setName()'>Change name</a><br></span>",
            link : link,
          }
      
        });
      

      【讨论】:

        【解决方案4】:

        在 AngularJS 指令中,scope 有 3 个选项

        1. false(使用父作用域)
        2. true(创建自己的范围并从父范围继承,即您也可以访问在父范围中定义的项目)
        3. {}(创建一个隔离范围)

        让我用 $rootScope 来演示一下

            app.run(function($rootScope){
              $rootScope.firstname = "Root scope name";
              $rootScope.rootValue = "Root value";
            });
        
            app.directive("sampleDirective",function(){
              return{
                template:"<div>{{firstname}}{{rootValue}}</div>",
         // here rootValue will be accessible as its inherited from parent. You can overwrite this as well
                scope : true,
                controller:['$scope',sampleDirectiveScope]
              };
            });
        
            function sampleDirectiveScope($scope){
              $scope.firstname = "child scope changing name - ";
            };
        
            app.directive("isolatedScopeDirective",function(){
              return {
                controller:isolatedFunction,
                template:" this has isolated scope ,<div>{{rootValue}}</div>", 
            // here rootValue will not be accessible because it is isolated and not inheriting from parent
                scope: {}
              };
            });
        
            function isolatedFunction($scope){ 
              //define values for this scope
            };
        

        检查这个live demo

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-10-09
          • 2014-03-28
          • 2014-01-12
          • 1970-01-01
          • 2017-01-17
          • 2015-09-02
          • 2016-03-06
          相关资源
          最近更新 更多