一尘不染

AngularJS 1.4指令:作用域,双向绑定和bindToController

angularjs

更新 :在代码的另一部分中一定有些愚蠢。现在可以使用,因此bindToController语法很好。

我们正在使用AngularJS 1.4,它引入了在指令中使用bindToController新方法

经过大量的阅读(也许并不能理解所有内容),我们如下定义了指令:

  .directive('mdAddress', function mdAddress() {
    var directive = {
      restrict: 'EA',
      scope: {},
      bindToController: {
        address: '='
      },
      templateUrl: 'modules/address/address.html',
      controller: AddressController,
      controllerAs: 'dir'
    };

从这样的另一个视图调用它:

  <md-address address="vm.address"></md-address>

先前已在视图控制器中定义:

  vm.address = {
    street: null,
    countryCode: null,
    cityCode: null,
    postalCode: null
  };

像这样在指令模板中引用变量:

  <md-input-container>
    <label>{{'ADDRESSNUMBER' | translate}}</label>
    <input type="number" ng-model="dir.address.streetNumber">
  </md-input-container>

我们花了4小时试图弄清楚为什么我们的指令不起作用。很好,它正在工作,但是控制器和指令之间的双向绑定没有实现,因此vm.address.street被无望地设置为null。

一段时间后,我们只是尝试了旧方法:

  .directive('mdAddress', function mdAddress() {
    var directive = {
      restrict: 'EA',
      scope: {
        address: '='
      },
      bindToController: true,
      templateUrl: 'modules/address/address.html',
      controller: AddressController,
      controllerAs: 'dir'
    };

它神奇地工作。知道 为什么 吗?


阅读 223

收藏
2020-07-04

共1个答案

一尘不染

更新:

感谢对此博客文章引用,我需要更新我的答案。从AngularJS 1.4开始,您似乎可以使用

scope: {},
bindToController: {
  variable: '='
}

它将(完全)执行与旧语法相同的操作:

scope: {
  variable: '='
},
bindToController: true

AngularJS源代码中的有用代码行解释了此行为:

if (isObject(directive.scope)) {
  if (directive.bindToController === true) {
    bindings.bindToController = parseIsolateBindings(directive.scope,
                                                     directiveName, true);
    bindings.isolateScope = {};
  } else {
    bindings.isolateScope = parseIsolateBindings(directive.scope,
                                                 directiveName, false);
  }
}
if (isObject(directive.bindToController)) {
  bindings.bindToController =
      parseIsolateBindings(directive.bindToController, directiveName, true);
}

资料来源:AngularJS 1.4.0

原始答案:

希望我能向您解释为什么您遇到的这种行为是正确的,以及您在哪里错过了理解范围绑定概念的原因。

让我解释一下,您在第一个代码段中做了什么:

.directive('mdAddress', function mdAddress() {
    var directive = {
      restrict: 'EA',
      scope: {},
      bindToController: {
        address: '='
      },
      templateUrl: 'modules/address/address.html',
      controller: AddressController,
      controllerAs: 'dir'
    };

使用scope: {},您为mdAddress指令创建了一个隔离范围(没有任何继承)。这意味着:在父控制器和您的指令之间不传递任何数据。

考虑到这一点,关于第二个代码段:

<md-address address="vm.address"></md-address>

vm.address来自您的父控制器/视图的数据将作为表达式分配给指令的address属性,但是由于您之前定义了隔离范围,因此数据不会传递到AddressControllerbindToController值中,因此无法使用。

让我们将scope对象定义视为“将传入哪些数据”,并将对象定义视为“
bindToController在我的视图的controllerAs对象中可用的数据”。

因此,现在让我们看一下最后一个(以及有效的代码片段):

.directive('mdAddress', function mdAddress() {
    var directive = {
      restrict: 'EA',
      scope: {
        address: '='
      },
      bindToController: true,
      templateUrl: 'modules/address/address.html',
      controller: AddressController,
      controllerAs: 'dir'
    };

在那里,您也创建了一个孤立的作用域,但是这次您添加了address要作为表达式传递的属性。因此,现在address从第二个片段的视图中传入的您将在控制器的作用域中可用。bindToController: true现在设置,会将当前作用域的所有属性绑定到控制器(或更可能是controllerAs对象)。现在,它可以按您期望的那样工作,因为数据将被传递到合并范围,并且数据将被传递到控制器的模板范围。

简要概述是否有助于您更好地理解scopebindToController定义对象的概念?

2020-07-04