Svelte 前端框架完全入门与进阶
引言:为什么要学习 Svelte?
在现代前端开发中,React、Vue、Angular 占据主流,但 Svelte 以完全不同的理念脱颖而出。它并非传统的运行时框架,而是一个编译器。在构建阶段,Svelte 会将你的组件编译为高度优化的纯 JavaScript 代码,无需虚拟 DOM,也无需庞大的运行时库。这意味着更小的打包体积、更快的启动速度和更高的执行效率。同时,Svelte 的语法简洁直观,状态管理天然内置,对初学者极其友好,也能帮助资深开发者写出更“瘦”的应用。
本教程将带你从零开始掌握 Svelte,涵盖核心概念、响应式系统、组件交互、过渡动画、状态管理以及进阶实战。无论你是前端新手还是想扩展技能栈的工程师,读完这份教程都能自信地构建 Svelte 应用。
第一章:快速上手
1.1 环境搭建与第一个 Svelte 项目
Svelte 官方推荐使用脚手架工具快速初始化项目。确保你的 Node.js 版本不低于 16。
npm create vite@latest my-svelte-app -- --template svelte
cd my-svelte-app
npm install
npm run dev
打开浏览器访问 http://localhost:5173,即可看到默认的 Svelte 页面。
你也可以使用 SvelteKit(全栈框架)搭建更复杂的应用:
npm create svelte@latest my-app
cd my-app
npm install
npm run dev
1.2 Svelte 组件的基本结构
每个 .svelte 文件就是一个组件,包含三个可选部分:<script>、<style> 和模板(HTML)。
<script>
let name = 'Svelte';
</script>
<h1>Hello {name}!</h1>
<style>
h1 {
color: #ff3e00;
}
</style>
<script>中的变量可以直接在模板中使用。- 样式的 CSS 默认是组件作用域的,不会影响其他组件。
第二章:核心语法与响应式
2.1 变量与文本插值
使用花括号 {} 包裹 JavaScript 表达式。
<script>
let count = 0;
const message = `当前计数:${count}`;
</script>
<p>{message}</p>
2.2 响应式赋值
Svelte 的响应式基于赋值。只要变量被重新赋值(=),相关 UI 就会自动更新。
<script>
let count = 0;
function handleClick() {
count += 1; // 触发更新
}
</script>
<button on:click={handleClick}>
点击了 {count} 次
</button>
- 注意:修改数组或对象时,必须通过赋值触发更新,如
arr = [...arr, newItem]或obj = {...obj, key: newValue}。
2.3 响应式声明:$: 语法
使用 $: 标记一个语句,当它的依赖发生变化时会自动重新执行。
<script>
let count = 0;
$: doubled = count * 2; // 声明式派生变量
$: if (count >= 10) {
alert('计数已达到 10');
}
</script>
<p>{count} 的两倍是 {doubled}</p>
2.4 条件渲染
{#if count > 10}
<p>大于 10</p>
{:else if count === 10}
<p>等于 10</p>
{:else}
<p>小于 10</p>
{/if}
2.5 列表渲染
<script>
let todos = [
{ id: 1, text: '学习 Svelte' },
{ id: 2, text: '构建项目' }
];
</script>
<ul>
{#each todos as todo (todo.id)}
<li>{todo.text}</li>
{/each}
</ul>
括号中的 todo.id 是键表达式,帮助 Svelte 精确追踪列表项变化,提升性能。
2.6 事件处理
<button on:click={() => count++}>
增加
</button>
支持事件修饰符:
<form on:submit|preventDefault={handleSubmit}>
<!-- 自动调用 event.preventDefault() -->
</form>
<button on:click|once={handleClick}>只触发一次</button>
2.7 双向绑定
使用 bind:value 将表单输入与变量双向绑定。
<script>
let name = '';
</script>
<input bind:value={name} placeholder="输入你的名字" />
<p>你好,{name}!</p>
同样可用于 <textarea>、<select>、复选框等。
第三章:组件化开发
3.1 组件属性 (Props)
父组件通过属性传递数据给子组件。子组件使用 export let 声明可接收的属性。
Child.svelte:
<script>
export let answer;
export let title = '默认标题'; // 可设默认值
</script>
<h2>{title}</h2>
<p>答案是:{answer}</p>
Parent.svelte:
<script>
import Child from './Child.svelte';
</script>
<Child answer={42} title="生命的意义" />
3.2 组件事件 (Component Events)
子组件通过 createEventDispatcher 向父组件发送事件。
Child.svelte:
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function send() {
dispatch('message', { text: '来自子组件的问候' });
}
</script>
<button on:click={send}>通知父组件</button>
Parent.svelte:
<script>
import Child from './Child.svelte';
function handleMessage(event) {
alert(event.detail.text);
}
</script>
<Child on:message={handleMessage} />
3.3 插槽 (Slots)
插槽让父组件可以向子组件内注入内容。
Card.svelte:
<div class="card">
<slot name="header">默认标题</slot>
<slot>默认内容</slot>
</div>
使用:
<Card>
<h3 slot="header">动态标题</h3>
<p>卡片主体内容</p>
</Card>
第四章:状态管理与生命周期
4.1 内置 Store
对于跨组件共享的状态,Svelte 提供了Store。它简单却强大,无需额外依赖。
创建 stores.js:
import { writable } from 'svelte/store';
export const count = writable(0);
在组件中使用:
<script>
import { count } from './stores.js';
function increment() {
count.update(n => n + 1);
}
</script>
<!-- 自动订阅语法:$count -->
<h1>计数:{$count}</h1>
<button on:click={increment}>+1</button>
$前缀让 Svelte 自动订阅 Store,当组件销毁时自动取消订阅。- Store 还可使用
readable、derived等。
4.2 组件生命周期函数
<script>
import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte';
onMount(() => {
console.log('组件已挂载');
return () => console.log('清理工作'); // 可选的清理函数
});
onDestroy(() => {
console.log('组件即将卸载');
});
beforeUpdate(() => {
console.log('每次 UI 更新前');
});
afterUpdate(() => {
console.log('每次 UI 更新后');
});
</script>
第五章:样式与动画
5.1 组件样式与全局样式
默认所有 <style> 中的 CSS 都只作用于当前组件。如需全局样式,使用 :global() 修饰符。
<style>
:global(body) {
background-color: #f0f0f0;
}
.button {
border-radius: 4px;
}
</style>
5.2 过渡与动画
Svelte 内置了优秀的过渡动画模块(svelte/transition 和 svelte/animate)。
<script>
import { fade, fly } from 'svelte/transition';
let visible = true;
</script>
<button on:click={() => visible = !visible}>切换</button>
{#if visible}
<p transition:fly={{ y: 200, duration: 500 }}>
内容滑入
</p>
{/if}
你还可以自定义过渡函数、控制 in/out 动画,以及使用 animate:flip 实现列表移动动画。
第六章:进阶实战与最佳实践
6.1 动作 (Actions)
动作是封装 DOM 操作的函数,可用于集成第三方库或自定义行为。
<script>
function tooltip(node, text) {
const tooltipEl = document.createElement('div');
tooltipEl.textContent = text;
tooltipEl.className = 'tooltip';
node.appendChild(tooltipEl);
return {
destroy() {
tooltipEl.remove();
}
};
}
</script>
<button use:tooltip={'提交表单'}>提交</button>
6.2 特殊的 $$props 和 $$restProps
在子组件中,$$props 包含所有传入的属性,$$restProps 包含未显式 export 的属性,可用于生成动态属性传递。
<script>
export let classProp = '';
</script>
<div {...$$restProps} class={classProp}>
内容
</div>
6.3 与 SvelteKit 搭配使用
SvelteKit 是基于 Svelte 的全栈框架,支持路由、服务端渲染 (SSR)、静态生成、API 路由等。学习完 Svelte 核心后,建议立即上手 SvelteKit,它能让你构建生产级应用如鱼得水。
文件路由示例:
src/routes/+page.svelte→/src/routes/about/+page.svelte→/aboutsrc/routes/api/users/+server.js→ API 端点
6.4 性能优化技巧
- 避免不必要的响应式依赖:使用常量而非 Store 传递静态配置。
- 列表使用键表达式:
{#each items as item (item.id)} - 缓存派生 Store:使用
derived时设定第二个参数为true以减少重新计算。 - 懒加载组件:结合动态
import()实现代码分割。
{#await import('./HeavyComp.svelte')}
<p>加载中...</p>
{:then module}
<svelte:component this={module.default} />
{/await}
第七章:总结与学习路径
恭喜你完成了 Svelte 从入门到进阶的学习!回顾一下我们掌握的核心内容:
- Svelte 编译器理念与零运行时优势
- 响应式赋值与
$:声明 - 组件化(Props、事件、插槽)
- 内置 Store 与生命周期
- 过渡动画与动作
推荐下一步:
- 用 Svelte 完成一个小项目,如待办事项、天气应用。
- 学习 SvelteKit 构建全栈应用。
- 探索官方示例与 REPL(svelte.dev/examples)。
Svelte 让前端开发变得简洁而愉悦,祝你编码愉快!