我正在尝试创建一系列可以导入到一个主要组件中的动态组件。当我可以将所有对象传递到一个绑定(bind)中而不是为要传递的每个对象创建多个绑定(bind)时,在组件内部嵌套组件要容易得多。因此,我创建了一个插件来演示我想要实现的目标。理想情况下,我希望能够将对象从父组件传递到子组件的ng-model中,而不必创建单独的绑定(bind)。

这是否可能,有人可以向我提供任何建议或解释,以说明为什么嵌套组件仅在本地而不是在整个 View 中更新模型吗?

基本上,如果您看下面的plunkr,我想让cNestedComponent发挥与cDirectComponent相同的作用,其中数据绑定(bind)从组件模板内部和模板外部进行更新。

http://plnkr.co/edit/vusx9rm1DnkbBlNBGyZG?p=preview

标记:

<h1> Data Comment => {{ data.comment }} </h1>
<c-direct-input plplaceholder="direct component" plmodel="data.comment" pltype="text"></c-direct-input>
<c-nested-input input-bindings="{type: 'text', model: 'data.comment', placeholder: 'nested component'}"></c-nested-input>

组件:
app.component('cNestedInput', {
  template: '\
    <h2> Nested Component </h2>\
    <p style="display: block;"> {{ $ctrl.inputBindings.model }} </p>\
    <input type="{{ $ctrl.inputBindings.type }}" placeholder="{{$ctrl.inputBindings.placeholder}}" ng-model="$ctrl.inputBindings.model" />\
  ',
  bindings: {
    inputBindings: '='
  },
  controller: function($scope) {}
});

app.component('cDirectInput', {
  template: '\
    <h2> Direct Component </h2>\
    <p style="display: block;"> {{ $ctrl.plmodel }} </p>\
    <input type="{{ $ctrl.pltype }}" placeholder="{{ $ctrl.plplaceholder }}" ng-model="$ctrl.plmodel" />\
  ',
  bindings: {
    plplaceholder: '@',
    plmodel: '=',
    pltype: '@'
  },
  controller: function($scope) {}
});

================================================== ======

更新

根据用户朱利安·塔森(Julien Tassin)的反馈,我创建了一个既干净又更新的插件,并且我想更好地演示我的目标:

https://plnkr.co/edit/cvYAdB?p=preview

Direct Component示例是实现我的目标的明确方法,但是当组件彼此嵌套时,我宁愿不必列出每个绑定(bind)。例如:
<c-nested-input input-bindings="$ctrl.input.inputBindings"/>

轻松输入然后再输入
<c-direct-input input-placeholder="{{$ctrl.inputPlaceholder}}" input-type="{{$ctrl.inputType}}" input-model="$ctrl.inputModel"/>\

每当我想将输入组件嵌套在父组件中时。

希望此更新可以进一步澄清我要查找的内容。

最佳答案

有几个问题使您的示例不起作用:

第一期:不可转让属性(property)

您有一个“不可分配”的问题。声明<c-nested-input input-bindings="{type: 'text', model: 'data.comment', placeholder: 'nested component'}"></c-nested-input>时,将创建一个不可分配的属性{type: 'text', model: 'data.comment', placeholder: 'nested component'}(顺便说一句,您在'data.comment'上有一个错误,应该是data.comment)。当您尝试在ngModel中为其分配值时,它将失败,因为您无法影响不可分配的表达式,甚至无法分配的表达式属性

因此,解决方案是在主 Controller 中设置可分配对象inputBindings并将其传递给组件。

第二期data.comment引用

那不是全部。
如果你试试 :

  $scope.data = {}
  $scope.inputBindings = {
    type: 'text',
    model: $scope.data.comment,
    placeholder: 'nested component'
  }

并将其传递给您的嵌套组件:
<c-nested-input input-bindings="inputBindings"></c-nested-input>

它不会像您想要的那样工作。
因为当您的嵌套将修改inputBindings.model时,它与data.comment的引用将不同。 =绑定(bind)代表inputBindings而不是其属性。

无法避免这种情况。

因此,您必须删除data.comment并按以下步骤工作:

标记:
<body ng-controller="MainCtrl">
  <h1> Data Comment => {{ inputBindings.model }} </h1>
  <hr/>
  <c-direct-input plplaceholder="direct component" plmodel="inputBindings.model" pltype="text"></c-direct-input>
  <c-nested-input input-bindings="inputBindings"></c-nested-input>
</body>

JS:
var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.inputBindings = {
    type: 'text',
    placeholder: 'nested component'
  }
});

app.component('cNestedInput', {
  template: '\
    <h2> Nested Component </h2>\
    <p style="display: block;"> {{ $ctrl.data.comment }} </p>\
    <input type="{{ $ctrl.inputBindings.type }}" placeholder="{{ $ctrl.inputBindings.placeholder}}" ng-model="$ctrl.inputBindings.model" />\
  ',
  bindings: {
    inputBindings: '='
  },
  controller: function() {}
});

app.component('cDirectInput', {
  template: '\
    <h2> Direct Component </h2>\
    <p style="display: block;"> {{ $ctrl.plmodel }} </p>\
    <input type="{{ $ctrl.pltype }}" placeholder="{{ $ctrl.plplaceholder }}" ng-model="$ctrl.plmodel" />\
  ',
  bindings: {
    plplaceholder: '@',
    plmodel: '=',
    pltype: '@'
  },
  controller: function() {

  }
});

plunker中的示例。

我的建议

我认为创建组件的更简洁的方法是一种混合方法:

就像是 :

JS:
app.component('cHybridInput', {
  template: '\
    <h2> Nested Component </h2>\
    <p style="display: block;"> {{ $ctrl.data.comment }} </p>\
    <input type="{{ $ctrl.options.type }}" placeholder="{{ $ctrl.options.placeholder}}" ng-model="$ctrl.ngModel" />\
  ',
  bindings: {
    ngModel: '=',
    options: '<'
  },
  controller: function() {}
});

HTML:
<c-hybrid-input ng-model="inputBindings.model" options="inputBindings"></c-hybrid-input>

10-05 20:41
查看更多