Svelte 学习笔记

为什么选择 Svelte

写了几年前后端分离的项目,常用的前端框架是 Vue 和 React。它们都是作为 SPA 设计的框架,没有 SEO 优化,初次加载比较慢。虽然有 Nuxt 和 Next 等框架来解决这个问题,但仍有些笨重。如果是小型项目,还是希望能有更轻量的框架。

Svelte 就是满足这方面需求的框架,设计上就考虑了 SEO 优化,并且很适合小型项目。

Svelte 的特点

  1. 写法更传统:上手难度小,更接近原生 HTML/CSS/JS
  2. 没有虚拟 DOM:没有运行时开销,性能更好
  3. 生成代码更小:编译时优化,生成的包体积更小,更适合小型项目

SvelteKit

SvelteKit 是 Svelte 团队推出的现代 Web 框架,包含了路由、服务端渲染、静态站点生成等功能。

创建项目

$ npx sv create
Need to install the following packages:
sv@0.8.10
Ok to proceed? (y)

┌  Welcome to the Svelte CLI! (v0.8.10)
◇  Where would you like your project to be created?
│  ./
◇  Which template would you like?
│  SvelteKit minimal
◇  Add type checking with TypeScript?
│  Yes, using TypeScript syntax
◆  Project created
◇  What would you like to add to your project? (use arrow keys / space bar)
│  tailwindcss
◇  Which plugins would you like to add?
│  typography
◆  Successfully setup add-ons
◇  Which package manager do you want to install dependencies with?
│  npm
◆  Successfully installed dependencies
◇  Project next steps ─────────────────────────────────────────────────────╮
│                                                                          │
│  1: git init && git add -A && git commit -m "Initial commit" (optional)│  2: npm run dev -- --open                                                │
│                                                                          │
│  To close the dev server, hit Ctrl-C                                     │
│                                                                          │
│  Stuck? Visit us at https://svelte.dev/chat                              │
│                                                                          │
├──────────────────────────────────────────────────────────────────────────╯
└  You're all set!

启动开发环境:

npm run dev -- --host

加了 --host 允许从别的机器访问。需要加 -- 用来将后面的参数传入 Vite。

编写内容

首页内容在 src/routes/+page.svelte 文件中。

组件

属性

在页面添加 script 代码块,并设定变量,即可在 HTML 中使用:

<script lang="ts">
  let name = "Svelte";
</script>

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

动态属性

<script>
  let src = '/tutorial/image.gif';
</script>

<img src={src} />
<img {src} />

作为属性时,不需要加引号。如果属性的名称和值同名,可以简化为 {src}

样式

在页面添加 style 代码块,设定样式。样式自动作用于当前组件:

<style>
  p {
    font-size: 20px;
  }
</style>

组件嵌套

在组件中 import 另一个组件,并在 HTML 中使用:

<script lang="ts">
  import Nested from './Nested.svelte';
</script>

<p>This is a component</p>
<Nested />

HTML 渲染

默认情况下,Svelte 会将 HTML 转义,以防止 XSS 攻击。如果需要渲染 HTML,可以使用 {@html} 指令:

<p>{@html string}</p>

响应式状态

Svelte 使用 $state 创建响应式变量。当这些变量改变时,Svelte 自动更新 DOM。

<script lang="ts">
  let count = $state(0);

  function increment() {
    count += 1;
  }
</script>

<button onclick={increment}>
  Clicked {count}
  {count === 1 ? 'time' : 'times'}
</button>

也可以用于数组:

<script lang="ts">
  let numbers = $state([0, 1, 2, 3, 4]);
</script>

派生状态

$derived 用于计算派生状态,当原始状态改变时会自动重新计算:

<script lang="ts">
  let numbers = $state([1, 2, 3, 4]);
  let total = $derived(numbers.reduce((t, n) => t + n, 0));
</script>

状态追踪

使用 $inspect() 输出状态变化,$state.snapshot() 获取当前快照:

<script lang="ts">
  let numbers = $state([1, 2, 3, 4]);
  let total = $derived(numbers.reduce((t, n) => t + n, 0));

  function addNumber() {
    numbers.push(numbers.length + 1);
    console.log($state.snapshot(numbers));
  }

  $inspect(numbers);
</script>

Props

Props 用于从父组件向子组件传递数据,使用 $props 接收:

<!-- Child.svelte -->
<script lang="ts">
  let { message = 'default' } = $props();
</script>

<p>{message}</p>

父组件中使用子组件并传递 props:

<!-- Parent.svelte -->
<script lang="ts">
  import Child from './Child.svelte';
</script>

<Child message="Hello from parent" />

事件

子组件通过事件将数据传递给父组件,使用 createEventDispatcher 或直接用 onclick 等事件处理:

<!-- Child.svelte -->
<script lang="ts">
  let { onchange } = $props();
</script>

<button onclick={() => onchange?.(123)}>Send message</button>

父组件监听事件:

<!-- Parent.svelte -->
<script lang="ts">
  import Child from './Child.svelte';

  function handleChange(value) {
    console.log(value);
  }
</script>

<Child onchange={handleChange} />

双向绑定

使用 bind: 指令实现双向绑定:

<script lang="ts">
  let name = $state('');
</script>

<input bind:value={name} />
<p>Hello {name}</p>

路由

SvelteKit 使用文件系统路由。在 src/routes/ 目录下创建文件或文件夹:

  • +page.svelte:页面组件
  • +layout.svelte:布局组件,适用于该目录及子目录
  • [id]:动态路由参数,如 /posts/[id]

获取路由参数

<script lang="ts">
  import { page } from '$app/stores';

  $: id = $page.params.id;
</script>

<p>Post ID: {id}</p>

常用工具

响应式声明

使用 $: 声明响应式代码,当依赖变化时自动执行:

<script lang="ts">
  let count = $state(0);

  $: doubled = count * 2;
  $: if (count > 10) console.log('count is over 10');
</script>

生命周期

常用的生命周期:

import { onMount, onDestroy } from 'svelte';

onMount(() => {
  console.log('组件挂载');
  return () => {
    console.log('清理');
  };
});

onDestroy(() => {
  console.log('组件卸载');
});

总结

Svelte 以其简洁的语法、出色的性能和小的包体积,成为小型项目和追求性能的团队的好选择。如果你来自 Vue 或 React 背景,转向 Svelte 会有新的体验和启发。


最后修改于 2025-06-15