我正在尝试了解Angular组件,但却无法让它们在嵌套组件配置中工作。基本上我想要做的是拥有一个定期更新值的父组件。然后我希望内部子组件绑定到父组件中的值,并在值更改时触发对$ onChanges的调用。
我做了一个jsFiddle来展示我想要完成的事情。父组件似乎正在工作并显示更新的值,但由于某种原因,子组件根本没有呈现。以下是我用来完成此任务的代码:
let app = angular.module('app', []);
class ParentController {
constructor($interval) {
this.value = 0;
$interval(() => this.value++, 1000);
}
}
let ParentComponent = {
controller: ParentController,
template: `<div>parent value: {{$ctrl.value}}</div>`
};
app.component('parent', ParentComponent);
class ChildController {
$onChanges(changesObj) {
console.log(changesObj);
}
}
let ChildComponent = {
bindings: {
value: '='
},
controller: ChildController,
require: {
parent: '^^parent'
},
template: `<div>child value: {{$ctrl.value}}</div>`
};
app.component('child', ChildComponent);
HTML:
<div ng-app="app">
<parent>
<child value="$ctrl.parent.value"></child>
</parent>
</div>
我做错了什么或是我想要完成的事情不可能?
答案 0 :(得分:0)
关于组件的事情是,除非你使用&#39; ng-transclude&#39;指令。
要显示您的子元素,您需要进行以下更改:
let ParentComponent = {
controller: ParentController,
transclude: true,
template: `<div>parent value: {{$ctrl.value}}</div><div ng-transclude></div>`
};
为了澄清,您将transclude: true
添加到组件对象以及模板中具有ng-transclude
指令的元素。任何具有ng-transclude
指令的元素都将其内容替换为<parent>
标记中的任何内容。
这只会让你的子组件呈现,你的HTML中还有另一个错误,就是你正在尝试使用
<child value="$ctrl.parent.value"></child>
在JavaScript中,它等同于未定义的$scope.$ctrl.parent.value
。
只需将您的HTML更改为:
<div ng-app="app">
<parent>
<child></child>
</parent>
</div>
并将子组件:
let ChildComponent = {
controller: ChildController,
require: {
parent: '^^parent'
},
template: `<div>child value: {{$ctrl.parent.value}}</div>`
};
然后你一切都好!
编辑(来自评论):
为了在父值更改时触发更新调用,您需要将ChildController
替换为以下内容:
let ChildController = function (scope) {
scope.$watch('$ctrl.parent.value', function (newValue, oldValue) {
console.log(newValue);
});
};
这会在子控制器上添加一个监视器,每次parent.value
更改时都会调用该函数。
答案 1 :(得分:0)
我对你的代码进行了修改。 有一种不同的方式来实现你想要做的事情。 这是我的代码,我将尝试解释它应该如何完成。
let app = angular.module('app', []);
class ParentController {
constructor($interval) {
this.value = 0;
$interval(() => this.value++, 1000);
}
}
let ParentComponent = {
controller: ParentController,
//here is the important edit. loading child component inside the parent component
template: `<div>
parent value: {{$ctrl.value}}
<child value="$ctrl.value"></child>
</div>`
};
app.component('parent', ParentComponent);
class ChildController {
$onChanges(changesObj) {
if(changesObj.hasOwnProperty('value')){
this.value=changesObj.value.currentValue //this referes to current scope.
}
}
}
let ChildComponent = {
bindings: {
value: '<'
},
controller: ChildController,
require: {
//parent: '^^parent' no need for this. we will use $onChanges
},
template: `<div>child value: {{$ctrl.value}}</div>`
};
app.component('child', ChildComponent);
<div ng-app="app"><parent></parent></div>
我在此代码示例中所做的事情:
我在父组件模板中包含了组件 因为你想要做的是在父母内部加载孩子。所以在父模板中添加了一个孩子。
删除了子组件定义中的Require,因为它会使您的子组件依赖于父组件。有一个不同的用例,你必须使用父。你最好使用绑定和$ onChanges来更新来自父母的孩子的数据,
为$ onChanges数据添加了一些验证。
如果(changesObj.hasOwnProperty(&#39;值&#39;)){ THIS.VALUE = changesObj.value.currentValue }
您需要了解更改obj是一个简单的更改对象。它有多个属性,如第一个change(),当前值,OldValue等。
你必须始终从这里验证你想要的东西。
我也将它设置为this.value
,这是当前的范围。
我们不是直接使用父作用域或绑定作用域变量。我正在创建一个新的范围对象,您将用它来显示数据。它将由绑定对象填充。
总体而言,这种情况正在发生
1.parent interval
更新父母范围
2. this.value
作为Bindings
3. $onChanges
验证绑定并将其分配给本地范围this.value
4.child模板在UI中呈现this.value