Angular如何通过普通类变量跳过变更检测阻止指定变量重渲染
实现方案
核心思路是把「需要同步视图的状态」和「仅逻辑层使用的状态」做隔离,完全可以通过普通类变量实现,不需要依赖信号、RxJS这类特殊响应式API,下面是两种可直接落地的实现方式:
方案1:拆分逻辑值和视图绑定值(零额外API依赖)
这是最贴合「普通类变量」要求的实现,不需要注入任何Angular核心API,只需要把b的实际逻辑值和给模板渲染的显示值拆成两个普通类属性即可:
@Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent { a = 1 // b的真实逻辑值,仅在类内部逻辑使用,更新不会同步到视图 private b = 2 // 专门给模板绑定的b显示值,只有主动更新才会同步到视图 bForView = this.b increase(){ this.a++ // 仅更新逻辑值,不更新bForView,视图上的b就会停留在初始值2 this.b++ } }
对应的模板只需要把原来绑定b的位置改成绑定bForView即可:
<p>{{ a }}</p> <p>{{ bForView }}</p> <button type="button" (click)="increase()">Increase</button>
如果后续某个时机需要把b的最新值同步到视图,只需要执行this.bForView = this.b就会自动触发更新。
方案2:不修改模板绑定,手动控制变更检测时机
如果你不想修改原有模板的绑定变量名,依然保持模板里写{{ b }},可以结合Angular原生的ChangeDetectorRef控制渲染时机,a和b本身依然是普通类变量:
import { Component, ChangeDetectorRef } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent { a = 1 b = 2 constructor(private cdr: ChangeDetectorRef) { // 把组件从自动变更检测树中脱离,关闭默认的自动重渲染 this.cdr.detach() // 首次手动触发渲染,显示初始值 this.cdr.detectChanges() } increase(){ // 第一步:先更新需要同步到视图的变量a this.a++ // 第二步:手动触发一次变更检测,此时b还未更新,视图只会同步a的最新值 this.cdr.detectChanges() // 第三步:最后更新b,此时变更检测已经执行完毕,b的变化不会被渲染到视图 this.b++ } }
这个方案不需要修改原有模板代码,b在逻辑层依然是可以正常读写的普通类变量,只是更新时机放在了变更检测执行之后,自然不会触发视图同步。
如果需要永久隐藏b的更新,哪怕其他操作触发了变更检测也不同步b的值,可以用getter固定视图返回值,全程不需要额外API:
export class AppComponent { a = 1 private _b = 2 private _bViewCache = this._b // 模板读取b时永远返回缓存的视图值 get b() { return this._bViewCache } increase() { this.a++ this._b++ } }
内容的提问来源于stack exchange,提问作者user19377529
相关产品推荐
相关产品推荐

