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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19774918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 16:44:59  来源:igfitidea点击:

Why are my AngularJS directives sharing scope?

javascriptangularjsangularjs-directive

提问by nickponline

I've tried to make a simple directive which displays a name and allows it to be change. When I put multiple directive on the name page they all seem to share the name attribute. What am I doing wrong?

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

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

回答by Stokes Player

As mentioned in previous answers, the default behavior of AngularJS directives is to share the scope that they are included in. This behavior is changed via the scopeparameter in the directive definition object.

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

You can view the documentation for the scope argument in this section of the AngularJS documents: http://docs.angularjs.org/api/ng.$compile#description_comprehensive-directive-api_directive-definition-object

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

This argument has three options:

这个论点有三个选项:

  1. scope: false- the default behavior of sharing the scope the directive is included in

  2. scope: true- create a new scope for the directive that acts like other child scopes and prototypically inherits from its parent scope

  3. scope: {}- create an isolated scope that does not prototypically inherit from its parent scope

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

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

  3. scope: {}- 创建一个独立的范围,该范围不典型地从其父范围继承

As you can see with the JSBin examples, both options 2 and 3 will work for your example. The difference is whether you want your new scopes isolated or not.

正如您在 JSBin 示例中看到的那样,选项 2 和选项 3 都适用于您的示例。不同之处在于您是否希望隔离您的新范围。

The directives section of the AngularJS guide has a good section on why isolated scope can help create better reusable modules with directives: AngularJS Guide: Isolating the Scope of a Directive

AngularJS 指南的指令部分有一个很好的部分,说明为什么隔离范围可以帮助创建更好的可重用模块与指令: AngularJS 指南:隔离指令的范围

回答by Nicolas ABRIC

By default if you don't isolate the scope of a directive you will share the "outside" scope with all instances of your person directive. With your current implementation you'd need to create a different controller each time in order to re-use such a directive.

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

BUT there is a solution to this flaw and it s called isolate scope. To do this, you can use a directive's scope option like so :

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

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,
}

You have a complete example and explenation over heresection Isolating the Scope of a Directive

你有一个完整的例子,explenation在这里部分隔离一个指令范围

回答by Stephane Rolland

By default, directives share the same scope. But if needed, you can use isolated scopefor your directives: use scope: {}as field in your directive definition.

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

  });

回答by Vignesh Subramanian

You have 3 options for scopein AngularJS directives

scope在 AngularJS 指令中有 3 个选项

  1. false(Uses parent scope)
  2. true(creates own scope and also inherits from parent, i.e you can access items defined in parent scope as well)
  3. {}(creates an isolated scope)
  1. false(使用父作用域)
  2. true(创建自己的范围并从父范围继承,即您也可以访问在父范围中定义的项目)
  3. {}(创建一个隔离的范围)

AngularJS Directives scope option

AngularJS 指令范围选项

Let me demonstrate this using $rootScope

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

Check this live demo

检查这个现场演示