$derived 派生
$derived 用于从一个或多个状态计算出新值。它会自动追踪依赖,只有依赖变化时才重新计算。
基本用法
svelte
<script>
let count = $state(0);
// doubled 依赖 count;count 变,doubled 自动重算
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>{count}</button>
<p>它的两倍是 {doubled}</p>取代 Svelte 4 的 $:
在 Svelte 4 里,派生值用响应式语句 $: 表示:
svelte
<!-- Svelte 4 写法(已过时) -->
<script>
let count = 0;
$: doubled = count * 2;
</script>$: 的问题在于:它的触发时机依赖编译器分析,容易让人困惑(「为什么这个没触发?」)。$derived 把它变成了一个显式的函数调用,依赖关系一目了然。
$derived vs $derived.by
当派生逻辑需要多条语句时,用 $derived.by 传入一个函数:
svelte
<script>
let items = $state([
{ name: '苹果', price: 5, qty: 2 },
{ name: '香蕉', price: 3, qty: 4 }
]);
// 简单表达式用 $derived
const count = $derived(items.length);
// 多语句逻辑用 $derived.by(() => { ... })
const total = $derived.by(() => {
let sum = 0;
for (const item of items) {
sum += item.price * item.qty;
}
return sum;
});
</script>
<p>共 {count} 种商品,总价 {total} 元</p>TIP
$derived(expr) 适合一行表达式;$derived.by(fn) 适合需要中间变量、循环、提前返回的复杂逻辑。
派生值是只读的
不要给 $derived 的结果赋值 —— 它由依赖决定:
svelte
<script>
let count = $state(0);
let doubled = $derived(count * 2);
// ❌ 错误:doubled 是只读的派生值
// doubled = 10;
</script>如果你想「改一个值让另一个跟着变」,用 $derived 单向派生即可;如果需要双向,看 $props 与 $bindable。
派生可以依赖派生
依赖链会自动串起来:
svelte
<script>
let price = $state(100);
let qty = $state(2);
const subtotal = $derived(price * qty);
const tax = $derived(subtotal * 0.1); // 依赖 subtotal
const total = $derived(subtotal + tax); // 依赖 subtotal、tax
</script>任何一个源头变化,整条链都会精确地重算。
试一试
拖动滑块,面积、周长、形状判断都是 $derived 实时算出来的:
派生状态 · $derivedSvelte 5 · Live
对应源码:
svelte
<script>
let width = $state(10);
let height = $state(5);
const area = $derived(width * height);
const perimeter = $derived(2 * (width + height));
const isSquare = $derived(width === height);
</script>
<input type="range" bind:value={width} />
<input type="range" bind:value={height} />
<div style:width="{width * 12}px" style:height="{height * 12}px"></div>
<p>面积 {area},周长 {perimeter},{isSquare ? '正方形' : '长方形'}</p>小结
| 要点 | 说明 |
|---|---|
$derived(expr) | 由依赖自动重算的派生值 |
$derived.by(fn) | 多语句派生逻辑 |
| 只读 | 不能给派生值赋值 |
| 自动追踪 | 依赖变化才重算,支持派生链 |
| 取代 | Svelte 4 的 $: 响应式语句 |
下一步:$effect 副作用。