问题
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 $scope
s 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