概述
今天来聊一聊Angular中的effect
, 使用过React框架的同学对effect
应该都不陌生,不过,Angular中的effect
和React中的effect
有所不同。
1 | effect(() => { |
effect
函数特点
effect
函数有如下特点:
effect
函数至少运行一次,无论effect
函数中是否读取signal
,也无论signal
的值是否发生变化。- 如果
effect
函数中读取了signal
,那么当signal
的值发生变化时,effect
函数会再次运行。 - 如果
effect
函数中没有读取signal
,那么effect
函数只会运行一次。当signal变化时,effect
函数不会再次运行。 effect
函数中不要更新signal
的值,否则会导致死循环。(因为signal更新—>effect运行—>更新signal—>effect运行…)
比如下面这个effect
函数,只会运行一次,因为effect
函数中没有读取count
。
1 | effect(() => { |
比如下面这个effect
函数,会导致死循环。
1 | effect(() => { |
effect
函数只能运行在injection context中(比如构造函数体内), 如果effect
函数的使用位置不对(比如放到了ngOnInit函数中),那么Angular会报如下错误:关于injection context的更多信息,可以查看这里。
1 | core.mjs:6643 ERROR RuntimeError: NG0203: effect() can only be used within an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.dev/errors/NG0203 |
effect
函数的使用场景
Effects are rarely needed in most application code, but may be useful in specific circumstances. Here are some examples of situations where an effect might be a good solution:
- Logging data being displayed and when it changes, either for analytics or as a debugging tool.
- Keeping data in sync with window.localStorage.
- Adding custom DOM behavior that can’t be expressed with template syntax.
- Performing custom rendering to a
<canvas>
, charting library, or other third party UI library.
Destroy effect
effect函数会在组件销毁时自动销毁,不需要手动清理。当然effect函数返回EffectRef
对象,可以手动调用destroy
方法销毁effect函数。
1 | const effectRef = effect(() => { |
untrack模式
https://angular.dev/guide/signals#reading-without-tracking-dependencies
cleanup function.
effect
函数中可以定义一个清理函数onCleanup
,当effect
函数被销毁时,清理函数会被调用。下面的代码演示了如何使用onCleanup
函数清理定时器。
1 | effect((onCleanup) => { |