Svelte 前端框架的核心概念

FreeGuideOnline 最新 2026-07-08

Svelte 核心概念详解:告别虚拟 DOM,拥抱编译器驱动的响应式

当你首次接触 Svelte 时,最震撼的一点或许是:它并不是一个传统意义上的运行时框架。Svelte 在构建阶段将你的组件编译为高效的原生 JavaScript,直接操作 DOM,无需引入庞大的运行时库。这种设计带来了更小的打包体积和极致性能,也造就了它简洁、直观的语法。本文将带你掌握 Svelte 最核心的概念,从零开始理解它的魅力。

1. 组件:.svelte 文件的三位一体

在 Svelte 中,每个 .svelte 文件就是一个组件。它同时容纳了三部分内容:

  • <script> – 组件逻辑(JavaScript)
  • <style> – 组件样式(CSS,默认作用域隔离)
  • 模板代码 – 组件的 HTML 结构

这三者共存于一个文件,让组件的封装性达到极致。

<script>
  let name = 'Svelte';
</script>

<style>
  h1 {
    color: #ff3e00;
  }
</style>

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

注意:

  • 花括号 {} 用于在模板中嵌入 JavaScript 表达式。
  • <style> 内的样式默认只作用于当前组件,不会泄漏到外部。

2. 响应式声明:$: 标记的魔法

Svelte 的响应式基于赋值触发。当你对组件内的变量重新赋值时,Svelte 会自动更新 DOM。更强大的地方在于响应式声明:使用 $: 标记的语句会在其依赖的值变化时重新运行。

<script>
  let count = 0;
  $: double = count * 2;        // 依赖 count,count 变化时重新计算

  $: {
    console.log(`count 是 ${count}`);
  }

  $: if (count > 10) {
    alert('计数大于 10!');
  }

  function increment() {
    count += 1;  // 赋值触发响应式
  }
</script>

<button on:click={increment}>
  点击了 {count} 次,双倍是 {double}
</button>

$: 很像 Vue 中的 computedwatch 的结合体,但语法更加灵活,可以直接书写任意语句。

3. 属性(Props):父传子的数据流

组件通过 export 关键字声明对外接收的属性(props)。这看起来和模块导出相反,但在 Svelte 中它代表“这个变量会从父组件传入”。

Child.svelte

<script>
  export let greeting;
  export let name = '陌生人'; // 可以设置默认值
</script>

<p>{greeting}, {name}!</p>

Parent.svelte

<script>
  import Child from './Child.svelte';
  let message = '你好';
</script>

<Child greeting={message} name="世界" />

属性是单向数据流,父组件更新 message 时会自动重新渲染子组件。

4. 事件处理:on: 指令

使用 on:事件名 监听 DOM 事件,支持内联处理或调用方法。

<script>
  function handleClick(e) {
    alert('按钮被点击');
  }
</script>

<button on:click={handleClick}>点击我</button>

支持事件修饰符,简化常见操作:

<button on:click|preventDefault={handleClick}>阻止默认行为</button>
<button on:click|once={handleClick}>只触发一次</button>

组件也可以转发事件(事件冒泡),但初学者可稍后再了解。

5. 双向绑定:bind: 指令

对于表单元素,可以用 bind:value 实现数据和输入的双向同步。

<script>
  let username = '';
  let accepted = false;
</script>

<input type="text" bind:value={username} placeholder="输入用户名" />
<input type="checkbox" bind:checked={accepted} />
<p>用户名:{username}</p>
<p>{accepted ? '已同意' : '未同意'}</p>

bind: 还可以绑定组件属性、尺寸属性(如 clientWidth)等,但需谨慎使用,避免数据流混乱。

6. 条件渲染与循环渲染

条件渲染 使用 {#if} 块,支持 {:else if}{:else}

<script>
  let loggedIn = false;
</script>

{#if loggedIn}
  <p>欢迎回来!</p>
{:else}
  <p>请登录。</p>
{/if}

循环渲染 使用 {#each} 块,需要唯一的 key 来提高更新性能:

<script>
  let todos = [
    { id: 1, text: '学习 Svelte' },
    { id: 2, text: '写项目' }
  ];
</script>

<ul>
  {#each todos as todo (todo.id)}
    <li>{todo.text}</li>
  {/each}
</ul>

如果数组为空,可以添加 {:else} 显示占位内容。

7. 生命周期:组件的关键时刻

Svelte 提供了几个生命周期函数来处理组件的挂载、更新和销毁:

  • onMount – 组件首次渲染到 DOM 后调用。常用作数据请求。
  • onDestroy – 组件销毁前调用。用于清理定时器等。
  • beforeUpdate / afterUpdate – 在数据变化,DOM 更新前后触发。
<script>
  import { onMount, onDestroy } from 'svelte';

  let data;

  onMount(async () => {
    const res = await fetch('/api/data');
    data = await res.json();
  });

  onDestroy(() => {
    console.log('组件被销毁了');
  });
</script>

{#if data}
  <div>{data.name}</div>
{/if}

8. 状态管理:可写 Store(writable)

当多个组件需要共享状态时,Svelte 提供了 Store 机制。最简单的 Store 是 writable

store.js

import { writable } from 'svelte/store';

export const count = writable(0);

在组件中使用 Store 需要加上 $ 前缀,这是 Svelte 的自动订阅语法糖,自动处理订阅和取消订阅:

<script>
  import { count } from './store.js';

  function increment() {
    $count += 1; // $count 自动订阅,可直接读写
  }
</script>

<h1>计数:{$count}</h1>
<button on:click={increment}>+1</button>

Store 也可以派生衍生值 (derived),但核心思想就是集中管理状态,组件通过 $store 自动响应。

9. 逻辑块与特殊元素

  • 异步块 {#await}:优雅处理 Promise 的等待、完成和拒绝状态。
  • <svelte:head>:向文档 <head> 插入内容,如标题。
  • <svelte:window>:监听 window 事件(如 resize),且可绑定属性。
  • <svelte:body>:监听 document.body 事件。
<svelte:head>
  <title>动态标题</title>
</svelte:head>

<svelte:window on:keydown={handleKey} bind:scrollY={y} />

这些特殊元素让组件与整个文档的交互变得非常简单。

10. 编译在,简约在——Svelte 的理念

理解以上概念后,你会明白 Svelte 的核心设计哲学:

  • 编译时魔法:响应式、过渡动画、样式作用域等均在构建阶段完成,最终生成无框架依赖的原生代码。
  • 代码即意图:减少样板代码,结构清晰。例如 $:, bind:, {#each} 等都有极强表现力。
  • 渐进式学习:组件、响应式、Store 等概念环环相扣,上手后可快速构建复杂应用。

从今天起,忘记“虚拟 DOM diff”,用 Svelte 的方式思考。当你写出 let count = 0; count += 1; 时,Svelte 已经帮你完成了一切更新。这就是编译器框架带来的自由。

下一步

建议立即在 Svelte REPL 中尝试这些概念,然后动手写一个计数器、待办列表或简单的博客应用。当你发现只需极少的代码就能完成同样功能时,便真正体会到了 Svelte 的强大。