在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

时间:2021-11-24 13:36:43

What is the difference and relationship between the $scope passed in a controller, and the $scope passed in a directive?

控制器中传递的$ scope与指令中传递的$ scope之间的区别和关系是什么?

And how would you set these up?

你会如何设置它们?

1 个解决方案

#1


1  

This is a brief explanation of what is the difference and relationship between the $scope passed in a controller, and the $scope passed in a directive is:

这是对控制器中传递的$ scope与指令中传递的$ scope之间的差异和关系的简要说明:

As you can see form the basic Angular setup below, $scope is passed to both the Angular Controller and to the Angular Directive. But what are the differences, and how do these $scopes relate and interact with each other?

正如您在下面看到的基本Angular设置,$ scope被传递给Angular Controller和Angular Directive。但是有什么区别,这些$范围如何相互关联和相互作用?

Basic Angular Setup

基本角度设置

Angular App:

angular.module('app', []);

Angular Controller:

angular.module('app').controller('mainCtrl', function($scope) {
  $scope.user = {
    name: 'Luke Skywalker',
    address: {
      street: 'PO Box 123',
      city: 'Secret Rebel Base',
      planet: 'Yavin 4'
    },
    friends: [
      'Han',
      'Leia',
      'Chewbacca'
    ]
  }
});

Angular Directive:

angular.module('app').directive('userInfoCard', function() {
  return {
    templateUrl: "userInfoCard.html",
    restrict: "E",
    controller: function($scope) {
      $scope.knightMe = function(user) {
        user.rank = "knight";
      }
    }
  }
});

There are 3 ways you can set up the relationship between the directive scope and the containing controller scope:

有三种方法可以设置指令范围和包含控制器范围之间的关系:

The default is for the directive to share the scope with the containing controller. This diagram illustrates this relationship.

缺省值是指令与包含控制器共享范围。该图说明了这种关系。

Directive Scope - Shared

指令范围 - 共享

You can see the parent $scope in purple, and we can see our User object created on the Parent Controller. The directive with the shared $scope lives entirely in the parent controller's $scope, and it has access to every object on the parent's controller $scope.

您可以在Purple中看到父$ scope,我们可以看到在父控制器上创建的User对象。具有共享$ scope的指令完全存在于父控制器的$ scope中,并且它可以访问父控制器$ scope上的每个对象。

If the directive had to modify or add items to the $scope, it would belong to the parent controller's $scope and not the directive. You can easily see this if you had to add a line to the controller and the directive to log out the $scope (console.log($scope);). You will note the $id of both ChildScopes would be the same.

如果指令必须修改或添加到$ scope的项,它将属于父控制器的$ scope而不是指令。如果必须向控制器添加一行,并且指令注销$ scope(console.log($ scope);),则可以很容易地看到这一点。你会注意到两个ChildScopes的$ id都是一样的。

Shared Scope is the simplest way to deal with $scope in directives.

共享范围是处理指令中的$ scope的最简单方法。

在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

Directive Inherited Scope

指令继承范围

The following diagram illustrates directive inherited $scope:

下图说明了指令继承的$ scope:

在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

Diagram 1

We once again have a user object created in the controller $scope, but with the directive set up to have inherited $scope.

我们再次在控制器$ scope中创建了一个用户对象,但指令设置为继承$ scope。

When we create a new item in the directive $scope, it will become Internal Data, and not visible to the parent $scope. In other words that item will live on the directive $scope and not on the parent $scope.

当我们在指令$ scope中创建一个新项时,它将成为内部数据,并且对于父$ scope不可见。换句话说,该项目将存在于指令$ scope而不是父$ scope。

See diagram 2 below:

见下图2:

在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

Diagram 2

There are several reasons why you would want to do this, the most common would be to encapsulate the data inside the directive.

您可能希望这样做有几个原因,最常见的是将数据封装在指令中。

To create a directive with inherited $scope, you add a scope property to the directive, and set it to true (setting it to false would be shared $scope - which is the default in any case).

要创建具有继承$ scope的指令,可以向指令添加scope属性,并将其设置为true(将其设置为false将为共享$ scope - 在任何情况下都是默认值)。

See directive code below:

请参阅以下指令代码:

Angular Directive:

angular.module('app').directive('userInfoCard', function() {
  return {
    templateUrl: "userInfoCard.html",
    restrict: "E",
    scope: true,
    controller: function($scope) {
      $scope.knightMe = function(user) {
        user.rank = "knight";
      }
    }
  }
});

When you log this out via the console, you will notice 2 ChildScope objects as before. But this time the $id is different for each $scope object.

当您通过控制台注销时,您将注意到2个ChildScope对象。但是这次每个$ scope对象的$ id都不同。

One thing to note: the directive ChildScope object has a property called $parent. This has the same $id as the controller ChildScope object. So the containing controller $scope has been set as the $parent of the directive $scope. You will also note the user object is visible in the parent $scope. This is true JavaScript inheritance.

有一点需要注意:指令ChildScope对象有一个名为$ parent的属性。它与控制器ChildScope对象具有相同的$ id。因此,包含控制器$ scope已被设置为指令$ scope的$ parent。您还将注意到用户对象在父$ scope中可见。这是真正的JavaScript继承。

Note: You will notice that the directive ChildScope object has a prototype (_proto_). When you look at the prototype, you can see that this is also that same scope object of the directive, making this true inheritance.

注意:您会注意到指令ChildScope对象具有原型(_proto_)。当您查看原型时,您可以看到这也是该指令的同一范围对象,从而实现了这种真正的继承。

Read:

https://developer.mozilla.org/en/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

http://javascript.info/tutorial/inheritance

The main difference here is not what the child scope can see on the parent scope, but instead what happens when the child scope creates new data. This data is internal to the child scope and not visible to the parent scope.

这里的主要区别不在于子范围可以在父范围上看到的内容,而是在子范围创建新数据时会发生什么。此数据在子范围内部,对父范围不可见。

Isolated Scope

The diagram below illustrates this scenario:

下图说明了这种情况:

在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

Once again we have a parent controller $scope that contains a user object. And as with inherited $scope, the data created in the directive $scope will be internal and not visible to the controller $scope.

我们再次拥有一个包含用户对象的父控制器$ scope。与继承的$ scope一样,在指令$ scope中创建的数据将是内部的,对控制器$ scope不可见。

But we have the issue of the directive $scope not being able to see the data on the controller $scope. Often we would want to see certain data elements of the controller $scope.

但是我们有指令$ scope无法查看控制器$ scope上的数据的问题。通常我们希望看到控制器$ scope的某些数据元素。

To solve this you can create a special binding between the isolated $scope and the parent $scope on an object by object basis. This way the isolated $scope cannot see everything on the parent $scope, but it can see specific items you make visible.

要解决此问题,您可以逐个对象地在隔离的$ scope和父$ scope之间创建一个特殊的绑定。这样,隔离的$ scope无法查看父$ scope上的所有内容,但它可以看到您可见的特定项目。

To do this, you change the true on the scope property to an object {}.

为此,您可以将scope属性的true更改为对象{}。

If you had to log this to the console, you would see once again that each ChildScope objects has its own unique $id. You will also note that the child scope (directive) still has a $parent object that is the parent scope (controller), but this time there is no parent scope linked to the prototype.

如果必须将此日志记录到控制台,您将再次看到每个ChildScope对象都有自己唯一的$ id。您还将注意到,子作用域(指令)仍然具有父作用域(控制器)的$ parent对象,但这次没有父作用域链接到原型。

To make the user object of the controller visible to the scope of the directive, you can add a property to the directive scope object of "user", and set its value to "=", telling the scope to expect an object to be passed to it with the value of "user".

要使控制器的用户对象对指令的作用域可见,可以将属性添加到“user”的指令作用域对象,并将其值设置为“=”,告诉作用域期望对象被传递用“user”的值来表示它。

The code below demonstrates this:

下面的代码演示了这一点:

angular.module('app').directive('userInfoCard', function() {
  return {
    templateUrl: "userInfoCard.html",
    restrict: "E",
    scope: {
      user: '='
    },
    controller: function($scope) {
      $scope.collapsed = ($scope.initialCollapsed === 'true');
      $scope.knightMe = function(user) {
        user.rank = "knight";
      }
      $scope.collapse = function() {
        $scope.collapsed = !$scope.collapsed;
      }
    }
  }
});

And that is the 3 ways to set up the relationship between the directive scope and the containing controller scope.

这是设置指令范围和包含控制器范围之间关系的3种方法。

A special thanks to Joe Eames. https://github.com/joeeames

特别感谢Joe Eames。 https://github.com/joeeames

#1


1  

This is a brief explanation of what is the difference and relationship between the $scope passed in a controller, and the $scope passed in a directive is:

这是对控制器中传递的$ scope与指令中传递的$ scope之间的差异和关系的简要说明:

As you can see form the basic Angular setup below, $scope is passed to both the Angular Controller and to the Angular Directive. But what are the differences, and how do these $scopes relate and interact with each other?

正如您在下面看到的基本Angular设置,$ scope被传递给Angular Controller和Angular Directive。但是有什么区别,这些$范围如何相互关联和相互作用?

Basic Angular Setup

基本角度设置

Angular App:

angular.module('app', []);

Angular Controller:

angular.module('app').controller('mainCtrl', function($scope) {
  $scope.user = {
    name: 'Luke Skywalker',
    address: {
      street: 'PO Box 123',
      city: 'Secret Rebel Base',
      planet: 'Yavin 4'
    },
    friends: [
      'Han',
      'Leia',
      'Chewbacca'
    ]
  }
});

Angular Directive:

angular.module('app').directive('userInfoCard', function() {
  return {
    templateUrl: "userInfoCard.html",
    restrict: "E",
    controller: function($scope) {
      $scope.knightMe = function(user) {
        user.rank = "knight";
      }
    }
  }
});

There are 3 ways you can set up the relationship between the directive scope and the containing controller scope:

有三种方法可以设置指令范围和包含控制器范围之间的关系:

The default is for the directive to share the scope with the containing controller. This diagram illustrates this relationship.

缺省值是指令与包含控制器共享范围。该图说明了这种关系。

Directive Scope - Shared

指令范围 - 共享

You can see the parent $scope in purple, and we can see our User object created on the Parent Controller. The directive with the shared $scope lives entirely in the parent controller's $scope, and it has access to every object on the parent's controller $scope.

您可以在Purple中看到父$ scope,我们可以看到在父控制器上创建的User对象。具有共享$ scope的指令完全存在于父控制器的$ scope中,并且它可以访问父控制器$ scope上的每个对象。

If the directive had to modify or add items to the $scope, it would belong to the parent controller's $scope and not the directive. You can easily see this if you had to add a line to the controller and the directive to log out the $scope (console.log($scope);). You will note the $id of both ChildScopes would be the same.

如果指令必须修改或添加到$ scope的项,它将属于父控制器的$ scope而不是指令。如果必须向控制器添加一行,并且指令注销$ scope(console.log($ scope);),则可以很容易地看到这一点。你会注意到两个ChildScopes的$ id都是一样的。

Shared Scope is the simplest way to deal with $scope in directives.

共享范围是处理指令中的$ scope的最简单方法。

在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

Directive Inherited Scope

指令继承范围

The following diagram illustrates directive inherited $scope:

下图说明了指令继承的$ scope:

在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

Diagram 1

We once again have a user object created in the controller $scope, but with the directive set up to have inherited $scope.

我们再次在控制器$ scope中创建了一个用户对象,但指令设置为继承$ scope。

When we create a new item in the directive $scope, it will become Internal Data, and not visible to the parent $scope. In other words that item will live on the directive $scope and not on the parent $scope.

当我们在指令$ scope中创建一个新项时,它将成为内部数据,并且对于父$ scope不可见。换句话说,该项目将存在于指令$ scope而不是父$ scope。

See diagram 2 below:

见下图2:

在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

Diagram 2

There are several reasons why you would want to do this, the most common would be to encapsulate the data inside the directive.

您可能希望这样做有几个原因,最常见的是将数据封装在指令中。

To create a directive with inherited $scope, you add a scope property to the directive, and set it to true (setting it to false would be shared $scope - which is the default in any case).

要创建具有继承$ scope的指令,可以向指令添加scope属性,并将其设置为true(将其设置为false将为共享$ scope - 在任何情况下都是默认值)。

See directive code below:

请参阅以下指令代码:

Angular Directive:

angular.module('app').directive('userInfoCard', function() {
  return {
    templateUrl: "userInfoCard.html",
    restrict: "E",
    scope: true,
    controller: function($scope) {
      $scope.knightMe = function(user) {
        user.rank = "knight";
      }
    }
  }
});

When you log this out via the console, you will notice 2 ChildScope objects as before. But this time the $id is different for each $scope object.

当您通过控制台注销时,您将注意到2个ChildScope对象。但是这次每个$ scope对象的$ id都不同。

One thing to note: the directive ChildScope object has a property called $parent. This has the same $id as the controller ChildScope object. So the containing controller $scope has been set as the $parent of the directive $scope. You will also note the user object is visible in the parent $scope. This is true JavaScript inheritance.

有一点需要注意:指令ChildScope对象有一个名为$ parent的属性。它与控制器ChildScope对象具有相同的$ id。因此,包含控制器$ scope已被设置为指令$ scope的$ parent。您还将注意到用户对象在父$ scope中可见。这是真正的JavaScript继承。

Note: You will notice that the directive ChildScope object has a prototype (_proto_). When you look at the prototype, you can see that this is also that same scope object of the directive, making this true inheritance.

注意:您会注意到指令ChildScope对象具有原型(_proto_)。当您查看原型时,您可以看到这也是该指令的同一范围对象,从而实现了这种真正的继承。

Read:

https://developer.mozilla.org/en/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

http://javascript.info/tutorial/inheritance

The main difference here is not what the child scope can see on the parent scope, but instead what happens when the child scope creates new data. This data is internal to the child scope and not visible to the parent scope.

这里的主要区别不在于子范围可以在父范围上看到的内容,而是在子范围创建新数据时会发生什么。此数据在子范围内部,对父范围不可见。

Isolated Scope

The diagram below illustrates this scenario:

下图说明了这种情况:

在控制器中传递的$ scope与在指令中传递的$ scope之间的差异和关系

Once again we have a parent controller $scope that contains a user object. And as with inherited $scope, the data created in the directive $scope will be internal and not visible to the controller $scope.

我们再次拥有一个包含用户对象的父控制器$ scope。与继承的$ scope一样,在指令$ scope中创建的数据将是内部的,对控制器$ scope不可见。

But we have the issue of the directive $scope not being able to see the data on the controller $scope. Often we would want to see certain data elements of the controller $scope.

但是我们有指令$ scope无法查看控制器$ scope上的数据的问题。通常我们希望看到控制器$ scope的某些数据元素。

To solve this you can create a special binding between the isolated $scope and the parent $scope on an object by object basis. This way the isolated $scope cannot see everything on the parent $scope, but it can see specific items you make visible.

要解决此问题,您可以逐个对象地在隔离的$ scope和父$ scope之间创建一个特殊的绑定。这样,隔离的$ scope无法查看父$ scope上的所有内容,但它可以看到您可见的特定项目。

To do this, you change the true on the scope property to an object {}.

为此,您可以将scope属性的true更改为对象{}。

If you had to log this to the console, you would see once again that each ChildScope objects has its own unique $id. You will also note that the child scope (directive) still has a $parent object that is the parent scope (controller), but this time there is no parent scope linked to the prototype.

如果必须将此日志记录到控制台,您将再次看到每个ChildScope对象都有自己唯一的$ id。您还将注意到,子作用域(指令)仍然具有父作用域(控制器)的$ parent对象,但这次没有父作用域链接到原型。

To make the user object of the controller visible to the scope of the directive, you can add a property to the directive scope object of "user", and set its value to "=", telling the scope to expect an object to be passed to it with the value of "user".

要使控制器的用户对象对指令的作用域可见,可以将属性添加到“user”的指令作用域对象,并将其值设置为“=”,告诉作用域期望对象被传递用“user”的值来表示它。

The code below demonstrates this:

下面的代码演示了这一点:

angular.module('app').directive('userInfoCard', function() {
  return {
    templateUrl: "userInfoCard.html",
    restrict: "E",
    scope: {
      user: '='
    },
    controller: function($scope) {
      $scope.collapsed = ($scope.initialCollapsed === 'true');
      $scope.knightMe = function(user) {
        user.rank = "knight";
      }
      $scope.collapse = function() {
        $scope.collapsed = !$scope.collapsed;
      }
    }
  }
});

And that is the 3 ways to set up the relationship between the directive scope and the containing controller scope.

这是设置指令范围和包含控制器范围之间关系的3种方法。

A special thanks to Joe Eames. https://github.com/joeeames

特别感谢Joe Eames。 https://github.com/joeeames