跳转至

620 Svelte/SvelteKit 前端开发

一句话概述:Svelte 是"编译型"前端框架,代码在构建时编译成原生 JS,不需要运行时库,性能极高且代码量极少,SvelteKit 是其全栈框架,类似 React 的 Next.js。

核心知识点速查表

知识点说明
最新版本Svelte 5.45+(2026年)
全栈框架SvelteKit 2.57+(基于 Vite 7)
核心特性Runes 响应式、编译时优化、零运行时
新特性Attachments、Remote Functions、Async SSR
打包工具Vite 7(SvelteKit 内置)
适用场景高性能Web应用、交互式UI、全栈应用

一、安装配置

# 创建 SvelteKit 项目(推荐)
npx sv create my-app                   # 交互式创建(选择模板和配置)
cd my-app
npm install                            # 安装依赖
npm run dev                            # 启动开发服务器 http://localhost:5173

1.1 项目结构

my-app/
├── src/
│   ├── routes/                # 基于文件系统的路由
│   │   ├── +page.svelte       # 首页 → /
│   │   ├── +layout.svelte     # 根布局
│   │   ├── about/
│   │   │   └── +page.svelte   # 关于页 → /about
│   │   └── blog/
│   │       ├── +page.svelte   # 博客列表 → /blog
│   │       └── [slug]/
│   │           └── +page.svelte  # 动态路由 → /blog/my-post
│   ├── lib/                   # 共享代码(可用 $lib 别名导入)
│   └── app.html               # HTML 模板
├── static/                    # 静态资源
├── svelte.config.js           # Svelte 配置
└── vite.config.ts             # Vite 配置

二、基本使用

2.1 组件基础(Svelte 5 Runes)

<!-- src/routes/+page.svelte -->
<script>
    // Svelte 5 使用 Runes(符文)系统做响应式
    let count = $state(0);              // $state:声明响应式变量(白话:值变了,页面自动更新)
    let doubled = $derived(count * 2);  // $derived:计算属性(白话:自动跟着 count 变)

    function increment() {
        count++;                        // 直接修改,页面自动更新(不需要 setState)
    }
</script>

<h1>计数器</h1>
<button onclick={increment}>
    点击次数: {count},双倍: {doubled}
</button>

<style>
    /* 样式自动局部作用域(不会影响其他组件) */
    button {
        padding: 8px 16px;
        background: #ff3e00;            /* Svelte 标志色 */
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
    }
</style>

2.2 Props 与组件通信

<!-- src/lib/components/UserCard.svelte -->
<script>
    // Svelte 5 用 $props() 接收属性
    let { name, email, age = 18 } = $props();  // age 有默认值
    // 白话:父组件传什么,这里就接什么
</script>

<div class="card">
    <h2>{name}</h2>
    <p>邮箱: {email}</p>
    <p>年龄: {age}</p>
</div>

<!-- 父组件中使用 -->
<!-- <UserCard name="张三" email="zhang@example.com" age={25} /> -->

2.3 条件与循环

<script>
    let items = $state(['苹果', '香蕉', '橙子']);  // 响应式数组
    let show = $state(true);                       // 控制显隐
</script>

<!-- 条件渲染 -->
{#if show}
    <p>内容可见</p>
{:else}
    <p>内容隐藏</p>
{/if}

<!-- 列表循环 -->
<ul>
    {#each items as item, index (item)}
        <li>{index + 1}. {item}</li>
    {/each}
</ul>

<!-- 异步数据 -->
{#await fetchData()}
    <p>加载中...</p>
{:then data}
    <p>数据: {data}</p>
{:catch error}
    <p>出错: {error.message}</p>
{/await}

2.4 Effects(副作用)

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

    // $effect:当依赖变化时自动执行(白话:监听变化做事情)
    $effect(() => {
        console.log(`count 变成了: ${count}`);  // count 变化时自动打印
        // 返回清理函数(可选)
        return () => {
            console.log('清理上一次的 effect');
        };
    });
</script>

三、SvelteKit 路由与数据

3.1 页面数据加载

// src/routes/blog/+page.server.ts(服务端加载数据)
// 白话:这个文件只在服务器运行,可以安全地连数据库、调用 API
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ fetch }) => {
    const res = await fetch('https://api.example.com/posts');  // 服务端获取数据
    const posts = await res.json();

    return {
        posts                              // 返回的数据传给页面组件
    };
};
<!-- src/routes/blog/+page.svelte -->
<script>
    let { data } = $props();              // 接收 load 函数返回的数据
</script>

<h1>博客列表</h1>
{#each data.posts as post}
    <article>
        <h2><a href="/blog/{post.slug}">{post.title}</a></h2>
        <p>{post.excerpt}</p>
    </article>
{/each}

3.2 表单操作(Form Actions)

// src/routes/login/+page.server.ts
import type { Actions } from './$types';
import { fail, redirect } from '@sveltejs/kit';

export const actions: Actions = {
    default: async ({ request }) => {
        const data = await request.formData();  // 获取表单数据
        const email = data.get('email');
        const password = data.get('password');

        if (!email || !password) {
            return fail(400, { error: '请填写所有字段' });  // 返回错误
        }

        // 验证逻辑...
        throw redirect(303, '/dashboard');  // 登录成功,重定向
    }
};
<!-- src/routes/login/+page.svelte -->
<script>
    let { form } = $props();              // 接收表单操作的返回值
</script>

<form method="POST">
    {#if form?.error}
        <p class="error">{form.error}</p>
    {/if}
    <input name="email" type="email" placeholder="邮箱" />
    <input name="password" type="password" placeholder="密码" />
    <button type="submit">登录</button>
</form>

3.3 API 路由

// src/routes/api/users/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';

export const GET: RequestHandler = async () => {
    const users = [
        { id: 1, name: '张三' },
        { id: 2, name: '李四' }
    ];
    return json(users);                    // 返回 JSON 响应
};

export const POST: RequestHandler = async ({ request }) => {
    const body = await request.json();     // 获取请求体
    return json({ id: 3, ...body }, { status: 201 });
};

四、高级用法

4.1 Stores(全局状态管理)

// src/lib/stores/auth.ts
import { writable } from 'svelte/store';

// writable:可读可写的全局状态(白话:所有组件共享的变量)
export const user = writable(null);        // 初始值为 null
export const isLoggedIn = writable(false);

// 自定义 store
function createCounter() {
    const { subscribe, set, update } = writable(0);
    return {
        subscribe,                          // 订阅变化
        increment: () => update(n => n + 1),
        decrement: () => update(n => n - 1),
        reset: () => set(0)
    };
}
export const counter = createCounter();
<!-- 在组件中使用 store -->
<script>
    import { user } from '$lib/stores/auth';
    // 用 $ 前缀自动订阅(白话:$user 会自动跟着 store 变化更新)
</script>
<p>当前用户: {$user?.name ?? '未登录'}</p>

4.2 Svelte 5 Attachments(新特性)

<script>
    import { createTooltip } from '$lib/actions/tooltip';

    // Attachments:声明式地给 DOM 元素附加行为
    // 白话:像给元素"贴标签"一样添加功能
    const tooltip = createTooltip('这是提示文字');
</script>

<button {@attach tooltip}>
    悬停查看提示
</button>

4.3 页面过渡动画

<script>
    import { fade, fly, slide } from 'svelte/transition';  // 内置过渡动画

    let visible = $state(true);
</script>

<button onclick={() => visible = !visible}>切换</button>

{#if visible}
    <!-- 淡入淡出 -->
    <p transition:fade={{ duration: 300 }}>淡入淡出效果</p>

    <!-- 从上方飞入 -->
    <p in:fly={{ y: -50, duration: 500 }} out:fade>飞入效果</p>

    <!-- 滑动 -->
    <p transition:slide>滑动效果</p>
{/if}

五、常见报错与解决

问题解决
$state is not defined确保使用 Svelte 5+,旧版本不支持 Runes
水合错误(Hydration mismatch)确保服务端和客户端渲染结果一致
Cannot use $state in .ts files$state 只能在 .svelte.svelte.ts 文件中使用
路由404检查 src/routes/ 目录下文件名是否正确(必须是 +page.svelte

六、速查表

操作代码/说明
创建项目npx sv create my-app
开发模式npm run dev
构建npm run build
响应式变量let x = $state(0)
计算属性let y = $derived(x * 2)
副作用$effect(() => { ... })
接收Propslet { name } = $props()
条件渲染{#if}{:else}{/if}
列表循环{#each items as item}{/each}
页面数据+page.server.tsload 函数
表单操作+page.server.tsactions
API路由+server.ts 的 GET/POST

七、同类工具对比

特性Svelte/KitReact/NextVue/NuxtSolid
运行时无(编译)~40KB~33KB~7KB
响应式RunesHooksCompositionSignals
学习曲线
生态增长中最大
性能极高极高
SSRSvelteKitNext.jsNuxtSolidStart

选型建议:追求极致性能和简洁代码选 Svelte;大团队/丰富生态选 React;渐进式需求选 Vue。


参考资料Svelte 官方文档 | SvelteKit 文档 | GitHub