Angular markForCheck vs detectChanges 在Angular中,有两种方法可以强制组件进行变更检测:markForCheck和detectChanges。 markForCheck方法是由ChangeDetectorRef服务提供的。当我们调用markForCheck方法时,Angular会标记当前组件及其子组件为需要进行变更检测。这意味着即使触发变更的代码不在当前组件中,Angular也会在下一次变更检测周期中检测并更新组件。 detectChanges方法也是由C
Angular markForCheck vs detectChanges 在Angular中,有两种方法可以强制组件进行变更检测:markForCheck和detectChanges。 markForCheck方法是由ChangeDetectorRef服务提供的。当我们调用markForCheck方法时,Angular会标记当前组件及其子组件为需要进行变更检测。这意味着即使触发变更的代码不在当前组件中,Angular也会在下一次变更检测周期中检测并更新组件。 detectChanges方法也是由C
我将从一个观点开始提出这个问题,我在StackOverflow上看到一个类似的问题,但那个问题只有一个回答区分了两者的差异。
我想问的是根据情况应该使用什么,以及一个方法或另一个方法可能存在的缺点。
我知道detectChanges
会立即对元素及其子元素进行变更检测循环,而markForCheck
只会将当前元素及其祖先标记为脏,并在下一次变更检测循环中对它们进行检查。
我之所以问这个问题,主要是因为我觉得在异步调用中我不应该总是使用markForCheck
。
例如,我有一个InputComponent
,它是一个常规HTML输入框的包装器。这个InputComponent
启用了ChangeDetectionStrategy.OnPush
。
当我向服务器发起异步调用并获取所需的数据时,我需要对该InputComponent
进行变更检测,以更新选项列表,而我有两种选择。
第一种选择(我觉得应该使用的)是detectChanges
,因为它只会对此组件应用检查,而markForCheck
会导致整个树分支都被检查。
那么我应该使用哪种方法,我是否需要使用markForCheck
,为什么?
Angular中的markForCheck和detectChanges之间的区别
在Angular中,有两个方法可以用于手动触发变更检测:markForCheck和detectChanges。然而,根据开发者的情况和需求,选择使用哪个方法可能会有所不同。下面将介绍这两个方法的出现原因以及解决方法。
首先,我们需要知道,使用detectChanges方法几乎没有好的场景。通常情况下,只有在项目中对组件的不可变性、状态管理和组件的变化没有得到良好管理时,才会使用detectChanges方法。而且,所有需要使用detectChanges方法的源代码都可以重写,以便不再需要手动调用这个方法。
相反,markForCheck方法则有一些较好的应用场景。在函数式编程中,对this的引用是不纯的,它会改变函数作用域之外的外部状态。打破函数式编程的最佳实践会引入需要修复的问题。如果你只使用纯函数来处理异步操作,就不需要调用markForCheck方法。但是,一旦引入了对this的引用,组件的状态就会发生变化,视图也需要被通知。
在RxJS的订阅中过度使用this会导致源代码难以维护。更好的做法是重写源代码,使用响应式编程,并在模板中使用async管道。关键是创建无状态组件,这样就不需要更新组件的属性,而是将所有操作都作为响应式流来处理。
如果设计组件为无状态组件,并使用RxJS处理所有数据处理,那么就不需要使用markForCheck方法。即使监听DOM事件,数据也可以传递到其他可观察对象,避免使用this。
虽然有时候确实需要调用markForCheck方法,但我建议你停下来重新思考你的方法,以避免使用它,因为应该有其他不需要它的方法。
但是,markForCheck方法会导致整个分支被更新,而不仅仅是一个单独的组件及其子组件。同时,你提到了不可变性。为什么我们要谈论不可变性和markForCheck/detectChanges方法呢?据我所知,markForCheck方法“计划”变更检测,而detectChanges方法立即执行变更检测。无论哪种情况,都是通过“变异”引起视图变化。不可变性是前端开发中的一种设计模式,用于管理“变异”,以便我们可以更有效地更新视图。markForCheck方法不会增加任何性能开销,因为Angular只会渲染发生变化的视图,而不会渲染整个分支。只有当你不使用OnPush变更策略时,整个分支才会被渲染。
关于使用RxJS的更多问题,我建议根据你的实际情况选择易于阅读和维护的方法。尽量多使用RxJS,并在模板中使用"thing$ | async"来学习。改变思维以便能够使用RXJS解决问题需要时间,但以后你会发现更多使用它的场景,并减少对markForCheck方法的使用。
关于async管道,它在组件中是可以访问的,例如可以这样使用:
至于为什么使用async管道而不是detectChanges方法,是因为async管道在组件中也可以访问。如果只是单纯地反映一个独立的组件的变化,使用detectChanges方法可能是更好的选择。RxJS很有价值,但它并不是万能的。
对于第三方库,如一些直接修改对象的Canvas库,你可以使用runOutsideAngular来避免变更检测。在这种情况下,重新赋值会引发许多问题。
总之,选择使用markForCheck方法还是detectChanges方法取决于你的具体情况和需求。尽量使用RxJS和async管道来处理数据和更新视图,避免手动调用detectChanges方法,以提高代码可维护性和性能。