Angular组件未触发变更检测却重渲染的原因探究
Angular变更检测疑惑:嵌套属性修改为何触发视图更新?
先看这段代码:
@Component({ selector: 'banana', template: ` <h1>We have {{ item.x }} bananas.</h1> `, }) export class Banana { @Input() item: { x: number } = { x: 0 }; } @Component({ selector: 'app-root', template: `<banana [item]="item"></banana>`, }) export class AppComponent { protected item = { x: 0 }; constructor() { setInterval(() => { this.item.x = Math.random(); }, 1000); } }
我之前一直认为这种情况不会生效——也就是item.x的变更不会显示在视图里,因为我知道Angular默认采用浅比较。而且Angular文档也明确说明:
修改对象引用:如果输入属性接收一个可变对象作为值,修改对象但保留引用时,Angular不会触发变更检测。这是预期行为,因为输入属性的前后值指向同一引用。
但实际测试后,上面的示例居然能正常更新视图,这让我十分困惑:到底是什么导致了视图更新?这和变更检测到底是什么关系?
我尝试给Banana组件添加OnChanges钩子:
[...] implements OnChanges { [...] ngOnChanges(changes: SimpleChanges): void { console.log(changes); }
结果完全没有日志输出——这符合文档描述,说明变更检测确实没检测到输入属性的变更。那视图到底是怎么完成更新的?
更新补充
有人提到是setInterval触发了NgZone导致视图更新(那是不是意味着使用setInterval存在性能问题?)。那再想另一个场景:数组的push操作明明不会改变数组的引用,按道理不该被检测到变更,但如果视图里用循环渲染数组内容,还是会自动更新,这又是为什么?
内容的提问来源于stack exchange,提问作者T_01
相关产品推荐
相关产品推荐

