这是因为您打破了 Angular 更改检测周期。
这是您单击第一个切换按钮后发生的情况:
1-您单击切换
2- ZoneJS,在点击事件中有钩子被通知(简单地说)
3-区域确保点击事件完成
4- Zone 会让 Angular 知道async
事件已经发生,我们必须检查组件并确保视图(DOM)反映了模型(模型/javascript 世界)。所以change detection
会运行,它会检测所有的变化并发现模板中有绑定(ng-if
)。
5- 之后ngIf
变为真,请注意,到目前为止,这一切都是同步的,ng-container
被创建的和你的templateOutlet
被创建的,你的hello
组件将被渲染。
再次注意:这都是同步的。
6 - 视图已更新,更改检测现已解除。
7 - 在你的hello
组件内部你触发另一个事件,它是created
通知父组件和你的父组件内部你正在改变数组,而 Angular 并不关心这一点,因为没有异步事件,你也没有更新了任何输入,您刚刚在更改检测完成他的工作后触发了另一个同步事件。
8- Array 现在已更新,但视图未更新(在父组件中)
9 - 再次单击,同样的情况发生,Angular 在第一次更改检测运行中更新父视图,您会看到数组反映在视图中。
为了证明我是对的:D:
onTemplateCreated() {
console.log('Got the event from chil');
this.template.push('Template created');
console.log('this.template',this.template);
}
您会看到在 click 之后,控制台显示了正确的数组,但是直到您再次单击后才会显示视图。
现在让我们切换到我的代码
onTemplateCreated() {
console.log('Got the event from chil');
this.template = [...this.template,'Template created'];
}
因为我没有发生变异并且引用正在更新,Angular 现在必须关心这个变化,但是仍然有一个问题,Angular 的变化检测器已经完成并且你在没有运行任何async
事件的情况下更新了模型,所以我们遇到了麻烦,因为 Angular 不喜欢在变更检测完成后更新模型,
所以你会被抛出一个错误,上面写着:
ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值
要解决这个问题,首先阅读我的另一篇文章以了解它,其次,您需要告诉 Angular 您知道自己在做什么并手动运行更改检测:
this._cd.detectChanges
或者,您可以使其异步:
onTemplateCreated() {
console.log('Got the event from chil');
setTimeout(()=>{
this.template = [...this.template,'Template created'];
})
}