派生状态使用 `$derived` 符号声明: ```svelte
{count} doubled is {doubled}
``` 表达式内部 `$derived(...)` 应当无副作用。Svelte 将禁止在派生表达式中进行状态更改(例如 `count++`)。 与`$state`一样,您可以标记类字段为`$derived`。 > \[注意\] Svelte 组件中的代码仅在创建时执行一次。如果没有`$derived`运行,`doubled`即使在`count`变化时也会保持其原始值。 ## `$derived.by` 有时您需要创建不适合简短表达式的复杂推导。在这种情况下,您可以使用`$derived.by`,它接受一个函数作为其参数。 ```svelte ``` 本质上,`$derived(expression)` 等同于 `$derived.by(() => expression)`。 ## 理解依赖关系 任何在 `$derived` 表达式(或 `$derived.by` 函数体)内同步读取的内容都被视为派生状态的 *依赖*。当状态发生变化时,派生状态将被标记为 *脏*,并在下一次读取时重新计算。 为将某个状态从依赖项处理中豁免,请使用 [`untrack`](svelte#untrack)。 ## 覆盖派生值 派生表达式在其依赖项更改时会被重新计算,但您可以通过重新分配它们来临时覆盖它们的值(除非它们被声明为`const`)。这可以用于诸如*乐观的用户界面*等情况,其中值是从“真相来源”(例如您的服务器上的数据)派生出来的,但您希望向用户显示即时反馈: ```svelte ``` > \[注意\] 在 Svelte 5.25 之前,派生变量是只读的。 ## 派生和反应性 不同于`$state`,它将对象和数组转换为[深度响应式代理,`$derived`值保持原样。例如,]($state#Deep-state)[在这种情况下...](/playground/untitled#H4sIAAAAAAAAE4VU22rjMBD9lUHd3aaQi9PdstS1A3t5XvpQ2Ic4D7I1iUUV2UjjNMX431eS7TRdSosxgjMzZ45mjt0yzffIYibvy0ojFJWqDKCQVBk2ZVup0LJ43TJ6rn2aBxw-FP2o67k9oCKP5dziW3hRaUJNjoYltjCyplWmM1JIIAn3FlL4ZIkTTtYez6jtj4w8WwyXv9GiIXiQxLVs9pfTMR7EuoSLIuLFbX7Z4930bZo_nBrD1bs834tlfvsBz9_SyX6PZXu9XaL4gOWn4sXjeyzftv4ZWfyxubpzxzg6LfD4MrooxELEosKCUPigQCMPKCZh0OtQE1iSxcsmdHuBvCiHZXALLXiN08EL3RRkaJ_kDVGle0HcSD5TPEeVtj67O4Nrg9aiSNtBY5oODJkrL5QsHtN2cgXp6nSJMWzpWWGasdlsGEMbzi5jPr5KFr0Ep7pdeM2-TCelCddIhDxAobi1jqF3cMaC1RKp64bAW9iFAmXGIHfd4wNXDabtOLN53w8W53VvJoZLh7xk4Rr3CoL-UNoLhWHrT1JQGcM17u96oES5K-kc2XOzkzqGCKL5De79OUTyyrg1zgwXsrEx3ESfx4Bz0M5UjVMHB24mw9SuXtXFoN13fYKOM1tyUT3FbvbWmSWCZX2Er-41u5xPoml45svRahl9Wb9aasbINJixDZwcPTbyTLZSUsAvrg_cPuCR7s782_WU8343Y72Qtlb8OYatwuOQvuN13M_hJKNfxann1v1U_B1KZ_D_mzhzhz24fw85CSz2irtN9w9HshBK7AQAAA==) ```svelte let items = $state([...]); let index = $state(0); let selected = $derived(items[index]); ``` ...您可以更改(或 `绑定:`)`选定的`属性,这将影响底层的`items`数组。如果`items`不是*深度响应式*的,修改`selected`将没有效果。 ## 解构 如果您使用与`$derived`声明一起的解构,则生成的所有变量都将具有响应性——这... ```js function stuff() { return { a: 1, b: 2, c: 3 } } // ---cut--- let { a, b, c } = $derived(stuff()); ``` ...大致相当于这个: ```js function stuff() { return { a: 1, b: 2, c: 3 } } // ---cut--- let _stuff = $derived(stuff()); let a = $derived(_stuff.a); let b = $derived(_stuff.b); let c = $derived(_stuff.c); ``` ## 更新传播 Svelte 使用一种称为*推拉响应性*的技术——当状态更新时,所有依赖于状态(无论是直接还是间接)的内容都会立即收到变更通知(即“推”),但派生值不会在实际上读取之前重新评估(即“拉”)。 如果派生值与其之前的值在引用上相同,则将跳过下游更新。换句话说,只有当 `large` 发生变化时,Svelte 才会更新按钮内的文本,而不是当 `count` 发生变化时,即使 `large` 依赖于 `count`: ```svelte ```