为什么我的AngularJS指令共享范围?

时间:2013-11-04 18:53:17

标签: javascript angularjs angularjs-directive

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

<!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>

4 个答案:

答案 0 :(得分:34)

如前面的答案中所述,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: {} - 创建一个独立的范围,不会从其父范围原型继承

  4. 正如您在JSBin示例中所看到的,选项2和3都适用于您的示例。不同之处在于您是否希望隔离新的示波器。

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

答案 1 :(得分:3)

默认情况下,如果不隔离指令范围,则将与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部分的完整示例和说明隔离指令的范围

答案 2 :(得分:2)

默认情况下,指令共享相同的范围。但是如果需要,您可以使用隔离范围作为指令:在指令定义中使用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,
    }

  });

答案 3 :(得分:1)

AngularJS指令中有scope的3个选项

  1. false(使用父范围)
  2. true(创建自己的范围并且也从父级继承,即您也可以访问父范围中定义的项目)
  3. {}(创建一个独立的范围)
  4. AngularJS Directives scope option

    让我用$ 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