The difference and relationship between the $scope passed in a controller, and the $scope passed in a directive

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-12 05:07:02

问题


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

And how would you set these up?


回答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:

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?

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.

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.

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

Directive Inherited Scope

The following diagram illustrates directive inherited $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.

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.

See diagram 2 below:

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).

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.

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.

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.

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:

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.

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.

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.

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

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.

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".

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.

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



来源:https://stackoverflow.com/questions/39507318/the-difference-and-relationship-between-the-scope-passed-in-a-controller-and-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!