已分离ChangeDetectorRef仍执行插值?Angular变更检测疑问
为什么detach子组件的变更检测器后,内容投影里的函数仍会被调用?
这个问题的核心在于Angular中内容投影的模板归属关系,咱们一步步拆解:
1. 内容投影的模板属于父组件的变更检测树
你在AppComponent的模板里定义的<ng-template>,哪怕被投影到app-rows组件中,它的上下文和变更检测管辖权仍然属于AppComponent,而不是RowsComponent。
AppComponent使用的是默认的ChangeDetectionStrategy.Default,这意味着任何触发变更检测的事件(比如你点击<h1>的点击事件)都会让Angular遍历AppComponent的整个变更检测树,包括它所有的模板表达式——当然也包括这个被投影出去的<ng-template>里的{{getName(row)}}。
2. RowsComponent的detach()只影响自身的变更检测
你在RowsComponent的ngAfterViewInit里调用changeDetector.detach(),只是让RowsComponent自己的变更检测器停止工作,也就是它自己模板里的内容(比如*ngFor="let row of rows"这部分)不会再被Angular检查更新。但这完全管不到父组件投影进来的模板,因为那部分属于AppComponent的变更检测范围。
验证思路:
如果想让getName不再被频繁调用,你可以试试这两种方式:
- 把
AppComponent的变更检测策略改成OnPush,这样只有当输入属性变化、组件内触发事件或手动调用markForCheck()时,才会触发变更检测; - 把
<ng-template>的定义移到RowsComponent内部,让它归属于子组件的变更检测树,这样detach()后就不会再执行里面的函数了。
内容的提问来源于stack exchange,提问作者Dieter Rehbein
相关产品推荐
相关产品推荐

