AngularJS 1.4指令:范围,双向绑定和bindToController

Leo*_*zes 12 javascript angularjs angularjs-directive angularjs-scope

更新:在代码的另一部分中一定是愚蠢的.它现在有效,所以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'
    };
Run Code Online (Sandbox Code Playgroud)

从另一个视图调用它:

  <md-address address="vm.address"></md-address>
Run Code Online (Sandbox Code Playgroud)

之前在视图控制器中定义:

  vm.address = {
    street: null,
    countryCode: null,
    cityCode: null,
    postalCode: null
  };
Run Code Online (Sandbox Code Playgroud)

引用指令模板中的变量,如下所示:

  <md-input-container>
    <label>{{'ADDRESSNUMBER' | translate}}</label>
    <input type="number" ng-model="dir.address.streetNumber">
  </md-input-container>
Run Code Online (Sandbox Code Playgroud)

我们花了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'
    };
Run Code Online (Sandbox Code Playgroud)

它神奇地起作用了.知道为什么

Con*_*Map 19

更新:

感谢参考此博客文章,我需要更新我的答案.从AngularJS 1.4看起来真的如此,你可以使用

scope: {},
bindToController: {
  variable: '='
}
Run Code Online (Sandbox Code Playgroud)

这将与旧语法(确切)相同的东西:

scope: {
  variable: '='
},
bindToController: true
Run Code Online (Sandbox Code Playgroud)

来自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);
}
Run Code Online (Sandbox Code Playgroud)

资料来源:AngularJS 1.4.0

原始答案:

希望,我可以解释一下为什么你所经历的这种行为是正确的,你在哪里错误地理解了那里的范围绑定的概念.

让我解释一下,你在第一段代码片段中做了些什么:

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

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

记住这一点,关于你的第二个代码片段:

<md-address address="vm.address"></md-address>
Run Code Online (Sandbox Code Playgroud)

vm.address来自您的父控制器/视图的表达式将被指定为指令的地址属性,但是在您之前定义了隔离范围时,数据不会传递到值AddressController,因此在bindToController值中不可用.

让我们将scope对象定义看作"将传入哪些数据",以及bindToController"我的视图中的控制器作为对象可以使用哪些数据".

那么,现在让我们看看最后一个(和工作代码片段):

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

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

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