理解 Angular(v21) 中的响应式上下文
发布: (2026年2月3日 GMT+8 03:02)
4 min read
原文: Dev.to
Source: Dev.to
Angular 信号中的响应式上下文
在 Angular Signal 系统中,响应式上下文是一种特殊的环境,在其中 Angular 的 依赖追踪引擎 处于激活状态。它是让信号知道谁在观察它们的“看不见的气泡”。
- 当你在响应式上下文 内部读取信号时,会自动 订阅该信号。
- 当你在响应式上下文 外部读取信号时,它的行为就像普通的函数调用,不会收到后续更新。
响应式上下文的创建位置
| 位置 | 如何创建响应式上下文 |
|---|---|
| 模板 | 在 HTML 中调用 mySignal() 会创建响应式上下文。 |
computed() | 传给 computed 的函数在响应式上下文内部执行。 |
effect() | effect 的函数体在响应式上下文内部执行。 |
在 Effect 中正确使用信号
import { effect } from '@angular/core';
constructor() {
effect(() => {
const x = mySignal(); // ✅ 这样是可以的
});
}
应避免的做法
在响应式上下文中进行副作用和信号变更
// ❌ 错误:在响应式上下文中创建或更新信号
readonly x = signal(0);
readonly y = signal(0);
readonly c = computed(() => {
const total = this.x() + this.y();
return { sum: signal(total) }; // ❌ 不良实践
});
readonly x = signal(0);
readonly c = computed(() => {
this.x.update(v => v + 1); // ❌ 不良实践
});
其他禁止的操作
- 调用可能会更新信号的 API。
- 直接操作 DOM。
- 使用条件性 effect,在已有 effect 中创建新的 effect 或信号。
// ❌ 错误:在另一个 effect 中创建 effect
effect(() => {
if (this.x() > 10) {
effect(() => console.log(this.x())); // ❌ 不良实践
}
});
批处理(无 Zone 的变更检测)
Angular 会把多个信号的更改合并在一起,并在单个批次中处理。这通过减少不必要的 effect 重执行和重新计算来提升性能。
- Angular 同步运行你的代码,追踪所有被修改的信号,任务完成后调度一次检查,以决定要运行哪些 effect。
- 在 effect 内部修改信号被视为“太晚”,可能导致循环依赖或无限循环。
使用 Effect 的指南
- 目的:Effect 应用于不会影响其他信号的副作用,例如日志记录、渲染或更新本地存储。
- 避免:触发可能导致信号变化的业务逻辑,因为无法保证哪些服务或 API 会改变信号。
- 渲染:每个 Angular 模板本质上都像一个 effect。当信号变化时,模板会自动重新评估。
推荐的 Effect 模式
import { effect } from '@angular/core';
// 日志示例
effect(() => {
console.log('Current value of x:', this.x());
});
// 更新本地存储
effect(() => {
localStorage.setItem('x', JSON.stringify(this.x()));
});
参考资料
- Angular Documentation
- YouTube: Kobi Hari (Angular Signals overview)