Svelte

编译时 UI 框架 - 无虚拟 DOM,精准更新,打包体积最小

TL;DR

一句话:Svelte 是编译器,不是框架——代码编译成原生 JS,零运行时开销。

核心优势

  • 没有虚拟 DOM - 编译成精确的 DOM 操作
  • 真正响应式 - 赋值就触发更新
  • 最小打包体积 - 不发送框架代码
  • Svelte 5 runes - 细粒度响应式原语

Core Concepts

概念 1:编译器,不是运行时

Svelte 把工作从浏览器转移到构建时。组件编译成高效的 JavaScript,直接操作 DOM。

<!-- 这会被完全编译掉 -->
<script>
  let count = $state(0);
</script>

<button onclick={() => count++}>{count}</button>

概念 2:Runes(Svelte 5)

Runes 是新的响应式系统。它们是编译器能理解的类函数宏。

<script>
  let count = $state(0);           // 响应式状态
  let doubled = $derived(count * 2); // 计算值

  $effect(() => {
    console.log(count);  // count 变化时运行
  });
</script>

概念 3:单文件组件

一切都在一个 .svelte 文件里——脚本、标记、样式(默认作用域隔离)。

<script>
  let name = $state('world');
</script>

<h1>Hello {name}!</h1>

<style>
  h1 { color: purple; }  /* 只影响这个组件 */
</style>

Quick Start

创建项目

npx sv create my-app
cd my-app
npm install
npm run dev

项目结构

my-app/
├── src/
│   ├── routes/        # SvelteKit 页面
│   │   └── +page.svelte
│   ├── lib/           # 共享组件
│   └── app.html
├── svelte.config.js
└── package.json

最小示例

<!-- src/routes/+page.svelte -->
<script>
  let count = $state(0);
</script>

<h1>Hello Svelte!</h1>
<button onclick={() => count++}>
  计数: {count}
</button>

运行

npm run dev
# 打开 http://localhost:5173

Gotchas

响应式需要 $state(Svelte 5)

<script>
  // ❌ 不是响应式的
  let count = 0;

  // ✅ 用 runes 才是响应式的
  let count = $state(0);
</script>

数组/对象需要重新赋值或使用 $state

<script>
  let items = $state([1, 2, 3]);

  // ✅ Svelte 5 中直接修改 $state 可以工作
  items.push(4);

  // 或者重新赋值
  items = [...items, 4];
</script>

Props 使用 $props()

<script>
  // Svelte 5 的方式
  let { name, count = 0 } = $props();
</script>

<h1>Hello {name}! 计数: {count}</h1>

双向绑定

<script>
  let value = $state('');
</script>

<!-- bind: 创建双向绑定 -->
<input bind:value>
<p>你输入了: {value}</p>

When to Use

适合

  • 性能关键的应用
  • 中小型项目
  • 不喜欢框架开销的开发者
  • 学习现代响应式概念

不适合

  • 需要最大生态/招聘池的团队(React 领先)
  • 需要大量第三方集成的项目
  • 非常大的企业应用(大规模实战经验较少)

对比

特性SvelteReactVue
打包体积极小40KB30KB
运行时
学习曲线简单中等简单
响应式编译时Hooks基于 Proxy

Next Steps

Cheatsheet

模式Svelte 5 语法
状态let x = $state(0)
派生let y = $derived(x * 2)
副作用$effect(() => { ... })
Propslet { prop } = $props()
绑定<input bind:value>
事件onclick={handler}
条件{#if x}...{/if}
循环{#each items as item}...{/each}
异步{#await promise}...{/await}