这是因为您打破了 Angular 更改检测周期。
这是您单击第一个切换按钮后发生的情况:
1-你点击切换
2- 在点击事件中有钩子的 ZoneJS 得到通知(简单地说)
3- Zone 确保点击事件完成
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:表达式在检查后已更改。以前的值
要解决这个问题,first read my other post to understand it,其次,您需要告诉 Angular 您知道自己在做什么并手动运行更改检测:
this._cd.detectChanges
或者,你可以让它异步:
onTemplateCreated() {
console.log('Got the event from chil');
setTimeout(()=>{
this.template = [...this.template,'Template created'];
})
}