如果我理解正确的话,您会问为什么绑定值会在LiteralsComponent
即使您不修改参考模板title
,而是改变对象。
简短的回答是因为你修改了两者:
this.title.name = "changed";
this.dTitle = {name: "changed"};
in the AppComponent.ngOnInit
。如果只修改this.title.name = "changed"
您将看到该模板未更新。
然而,这是一个非常有趣的问题,需要详细探讨
我们首先只从this.title
没有this.dTitle
.
首先要了解的是,当您在模板中指定以下内容时:
{{title.name}}
这就是 Angular 所做的。它试图找到title
当前组件实例上的对象,然后获取name
来自它的属性并将其反映在 DOM 中。但具有以下配置:
class AppComponent {
title = { name: 'original' }
ngOnInit(): void {
setTimeout(() => {
alert("About to change");
this.title.name = "changed";
}, 1000);
}
}
class LiteralsComponent {
@Input() title;
}
the title
对象是the same在两个组件中(指向相同的内存位置)。
因此,当 Angular 运行更改检测时LiteralsComponent
组件,它访问您在此处更改的同一对象AppComponent
:
ngOnInit(): void {
setTimeout(() => {
alert("About to change");
this.title.name = "changed";
}, 1000);
}
这里有趣的观察是变化未检测到根本不与OnPush
也没有它:
class LiteralsComponent {
@Input() title;
ngOnChanges(changes) {
// will be triggered only for the first CD cycle,
// and won't be triggered when `title` is updated
}
}
现在,最后一件事是要了解 DOM 何时更新。根据本文 https://hackernoon.com/everything-you-need-to-know-about-change-detection-in-angular-8006c51d206f,它会在当前组件的 CD 期间更新。这意味着如果当前组件没有被检查,DOM将不会被更新。所以我们指定onPush
为了LiteralsComponent
:
changeDetection: ChangeDetectionStrategy.OnPush,
视图不会更新。
但是,它已在您的问题中更新。为什么?
还有这个地方dTitle
开始发挥作用。使用此属性,您实际上是在修改参考和 Angular检测绑定变化并运行 CDLiteralsComponent
成分。上面我们了解到,当 CD 运行时,DOM 会更新。所以 Angular 也更新了{{title.name}}
因为它指向同一个对象AppComponent
, 虽然它没有检测到它被改变了.