1. Svelte 5 的 Runes($state/$derived/$effect)与旧版 $: 语法的差异与迁移要点?
Svelte 5 的 runes($state/$derived/$effect)与旧版 $: 响应式语法有何差异?迁移时有哪些要点?
- 旧版基于变量赋值静态分析的隐式响应式与其限制
- runes 显式声明的形态与模块级可用性
- 迁移工具、混用边界与逐组件转换策略
旧版 Svelte 的响应式基于编译器对变量赋值的静态分析:声明 let 变量即为响应式,$: 声明派生语句。这种隐式机制的限制在于:无法在运行时动态创建响应式变量、不能在 .js/.ts 模块文件中使用、在循环、闭包与复杂控制流中容易失效,且依赖编译器对"赋值位置"的识别,语义不够直白。runes 模式把响应式声明显式化:let count = $state(0) 声明响应式状态,let doubled = $derived(count * 2) 声明派生值,$effect(() => {...}) 声明副作用,并可在任何 .svelte.js/.svelte.ts 模块中使用,运行时也能动态创建,语义清晰且可静态分析。
迁移要点:let count = 0 改为 let count = $state(0);$: doubled = count * 2 改为 $derived;$: 内包含副作用的语句改为 $effect;事件中赋值与模板引用基本不变。官方提供迁移工具可自动转换大部分旧语法,组件可以逐文件迁移,legacy 模式与 runes 模式在单个组件内可以混用,但新代码应统一 runes 风格;迁移后用类型检查与测试回归兜底。
本题考察 Svelte 响应式机制的核心演进:从"编译器猜测你的意图"到"开发者显式声明"(隐式到显式)。回答要点是旧语法局限、runes 三原语语义与可操作的迁移路径。
<script>
let count = $state(0);
let doubled = $derived(count * 2);
$effect(() => console.log(doubled));
</script>
<button onclick={() => count++}>{doubled}</button>