我正在尝试创建一系列可以导入到一个主要组件中的动态组件。当我可以将所有对象传递到一个绑定(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>