controller中传入的$scope和directive中传入的$scope的区别与关系

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

controller传入的$scopedirective传入的$scope有什么区别和关系?

你会如何设置它们?

这里简单解释一下controller传入的$scope和[=传入的$scope的区别和关系18=] 是:

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

基本Angular设置

Angular应用程序:

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

Angular 控制器:

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 指令:

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 之间的关系:

默认为directiveshare包含controller的作用域。此图说明了这种关系。

指令范围 - 共享

您可以看到紫色的父项 $scope,我们可以看到我们的 User object 在父项 Controller 上创建。具有共享 $scope 的指令完全存在于父级 controller's $scope 中,并且它可以访问父级 controller $scope.

中的每个对象

如果指令必须修改或向 $scope 添加项目,它将属于 parent controller's $scope 而不是 directive。如果您必须在 controllerdirective 中添加一行以注销 $scope (console.log($scope);),您可以很容易地看到这一点。您会注意到两个 ChildScopes$id 是相同的。

Shared Scope 是处理 directives 中的 $scope 最简单的方法。

指令继承范围

下图说明directive继承$scope

图表 1

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

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

见下图2:

图2

您想要这样做的原因有多种,最常见的是 封装 directive 中的数据。

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

请参阅下面的 directive 代码:

Angular 指令:

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 对象。但是这次每个 $scope 对象的 $id 是不同的。

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

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

阅读:

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

http://javascript.info/tutorial/inheritance

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

隔离作用域

下图说明了这种情况:

我们再次有一个包含 user 对象的父 controller $scope。与 inherited $scope 一样,在 directive $scope 中创建的数据将是 internal不可见 controller $scope

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

为了解决这个问题,您可以在一个对象一个对象的基础上,在孤立的 $scope 和父对象 $scope 之间创建一个特殊的绑定。这样,孤立的 $scope 无法看到父 $scope 上的所有内容,但它可以看到您设置为可见的特定项目。

为此,您将 scope 属性 上的 true 更改为 object { }

如果您必须将此记录到控制台,您会再次看到每个 ChildScope 对象都有其唯一的 $id。您还会注意到,子作用域 (directive) 仍然有一个 $parent 对象,它是父作用域 (controller),但这次没有链接到 原型 的父作用域。

要使 controlleruser 对象对 directive 的范围可见,您可以添加一个 属性 "user" 的指令作用域对象,并将其值设置为“=”,告诉作用域期望传递给它的值为 "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