计算信号
派生会自动更新的值。
计算信号 是 CoddyKit 上的免费 Angular Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Angular Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Angular Academy 课程共包含 4 节课。
什么是计算信号
computed() 信号根据一个或多个其他信号派生值。每当源信号发生变化时,计算值都会延迟重新计算——只有在有代码读取它时才会计算。
计算信号是只读的:您不能对其调用 .set()。
创建 computed
向 computed() 传入一个函数。Angular 会自动跟踪您在其中读取的每个信号。
import { signal, computed } from '@angular/core';
const price = signal(100);
const quantity = signal(2);
const total = computed(() => price() * quantity());
console.log(total()); // 200自动跟踪依赖
您不需要手动声明依赖。在回调函数中读取 price() 和 quantity() 会自动将它们注册为依赖。
如果某个信号是有条件读取的,而本次执行未到达该分支,那么本次执行不会跟踪它。
const showTax = signal(false);
const tax = signal(20);
const base = signal(100);
const final = computed(() =>
showTax() ? base() + tax() : base()
);
// When showTax() is false, "tax" is NOT a dependency惰性计算与记忆化
计算信号只会在被读取时运行,并缓存其结果。如果在源信号未变化的情况下读取它两次,该函数只会运行一次。
const a = signal(1);
const doubled = computed(() => {
console.log('recompute');
return a() * 2;
});
doubled(); // logs "recompute", returns 2
doubled(); // cached, returns 2, no log串联计算信号
计算信号可以依赖其他计算信号,从而形成响应式图。
const firstName = signal('Ada');
const lastName = signal('Lovelace');
const fullName = computed(() => firstName() + ' ' + lastName());
const greeting = computed(() => 'Hello, ' + fullName());
console.log(greeting()); // Hello, Ada Lovelace在组件中使用 computed
计算信号非常适合用于组件。只有当计算值实际发生变化时,模板才会重新渲染。
import { Component, signal, computed } from '@angular/core';
@Component({
selector: 'app-cart',
template: '<p>Total: {{ total() }}</p>'
})
export class CartComponent {
items = signal([10, 20, 30]);
total = computed(() => this.items().reduce((a, b) => a + b, 0));
}计算信号是只读的
尝试设置计算信号会导致编译时错误。计算信号纯粹用于表达派生状态。
const count = signal(0);
const doubled = computed(() => count() * 2);
// doubled.set(10); // ERROR: Property 'set' does not exist
count.set(5); // OK - update the source instead
console.log(doubled()); // 10相等性与跳过重新计算
默认情况下,计算信号使用 Object.is 进行比较。如果新的计算值与旧值相等,就不会通知依赖它的对象,从而避免无用的工作。
const value = signal(2);
const isEven = computed(() => value() % 2 === 0);
// value 2 -> 4 -> 6 all yield isEven() === true
// Dependents of isEven do NOT re-run on those changes自定义相等函数
您可以传入 equal 选项,控制何时认为计算值发生了变化;这对对象或数组很有用。
const data = signal({ id: 1, name: 'A' });
const view = computed(
() => data(),
{ equal: (a, b) => a.id === b.id }
);
// Dependents re-run only when the id changes避免在 computed 中产生副作用
计算信号必须是纯函数:不能发起 HTTP 调用、不能将日志记录作为行为,也不能修改其他信号。副作用应放在 effect() 中。保持计算信号纯净,可以让响应式图保持可预测。
计算信号与方法
模板方法会在每个变更检测周期中运行。计算信号只会在其依赖发生变化时运行,并且会缓存结果——对于派生值而言,效率高得多。
// Method: recalculates every CD cycle
getTotal() { return this.items().reduce((a, b) => a + b, 0); }
// Computed: memoized, runs only on item change
total = computed(() => this.items().reduce((a, b) => a + b, 0));快速检查
检验您对计算信号的理解。
总结:计算信号
您已经了解到,computed() 会创建具有只读派生信号特征的信号,并提供自动依赖跟踪、惰性求值和记忆化。
- 保持其纯净——不要产生副作用。
- 它们可以依赖其他计算信号。
- 使用
equal进行自定义变更检测。
接下来:使用 effect() 运行副作用。
常见问题解答
「计算信号」课时是免费的吗?
是的 — 「计算信号」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Angular Academy 课程的其余内容,请升级到 CoddyKit PRO。 Angular Academy 课程共包含 4 节课。
「计算信号」这节课中我会学到什么?
派生会自动更新的值。 你通过在浏览器中直接运行的动手代码来练习 Angular Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Angular Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Angular Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「计算信号」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Angular Academy 课中编写并运行代码吗?
能。每节 Angular Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。