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

时间:2016-09-15 09:18:15

标签: angularjs inheritance angularjs-directive scope angular-controller

$scope传递的controller$scope传递的directive之间有何区别和关系?

你会如何设置它们?

1 个答案:

答案 0 :(得分:1)

这是对$scope中传递的controller$scope中传递的directive之间差异和关系的简要说明。 :

正如您在下面的基本角度设置中所见,$scope传递给Angular ControllerAngular Directive。但是有哪些差异,这些$scope如何相互关联和相互作用?

基本角度设置

Angular App:

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

角度控制器:

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";
      }
    }
  }
});

您可以通过3种方式设置directive scope与包含controller scope之间的关系:

默认情况下,directive 分享 范围包含controller。该图说明了这种关系。

指令范围 - 共享

您可以看到紫色的父$scope,我们可以在父User object上看到我们的Controller。共享$ scope的指令完全存在于父controller's $scope中,并且它可以访问父controller $scope上的每个对象。

如果指令必须修改或添加到$ scope的项目,它将属于parent controller's $scope而不是directive。如果您必须在controllerdirective添加一行以注销$scope (console.log($scope);,则可以轻松查看此内容。您会注意到 ChildScopes $ id 将是相同的。

共享范围是处理$scopedirectives的最简单方法。

enter image description here

指令继承范围

下图说明了directive继承的$scope

enter image description here

图1

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

当我们在directive $scope中创建新项目时,它将变为内部数据,并且对父$scope不可见。换句话说,该项目将位于directive $scope而不是父级$scope上。

见下面的图表

enter image description here

图2

您可能希望这样做有几个原因,最常见的是封装 directive内的数据。

要创建包含继承$scope的指令,请在指令中添加scope property,并将其设置为true(将其设置为false将被共享$scope - 这在任何情况下都是默认的。)

请参阅下面的directive代码:

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";
      }
    }
  }
});

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

需要注意的一件事directive ChildScope对象有一个名为 $ parent 的属性。这与controller ChildScope对象具有相同的 $ id 。因此,包含controller $scope已设置为directive $scope $ parent 。您还会注意到用户对象在 $scope中可见。这是真正的JavaScript 继承

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

阅读:

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

http://javascript.info/tutorial/inheritance

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

隔离范围

下图说明了这种情况:

enter image description here

我们再次拥有包含用户对象的父controller $scope。与继承 $scope一样,directive $scope中创建的数据将内部不可见controller $scope

但是我们遇到directive $scope无法查看controller $scope上的数据的问题。我们通常希望查看controller $scope的某些数据元素。

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

为此,您可以将范围属性中的 true 更改为对象{}

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

要使controller范围内directive用户对象可见,您可以将属性添加到" user&的指令范围对象中#34;,并将其值设置为" =",告诉范围期望将对象传递给它,其值为" user"。

以下代码演示了这一点:

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;
      }
    }
  }
});

这是设置directive范围与包含controller范围之间关系的3种方法。

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