命令式组件 API
本教程共 50 篇 · 第 35 篇 · 更新于 2026-08-05 · 约 6 分钟阅读
35. 命令式组件 API
本节目标:掌握 Svelte 5 的
mount、unmount、hydrate、render四个命令式 API,学会在非 SvelteKit 环境(如纯 HTML 页面、后端渲染)中手动操控 Svelte 组件的生命周期。
什么时候需要命令式 API
用 SvelteKit 时,框架帮你把组件挂载到页面、处理水合,你基本不用操心这些底层细节。但有些场景你不在 SvelteKit 里:
- 把 Svelte 组件嵌入到已有的多页应用(比如 Django、Laravel 项目)
- 做一个独立的组件库,给别人通过
<script>引入使用 - 在 Node 服务器上把组件渲染成 HTML 字符串
这些场景就需要 Svelte 的命令式组件 API。
Note如果你在用 SvelteKit,这一章了解即可,日常开发几乎用不到。但理解底层原理能帮你更好地调试问题。
mount:挂载组件
mount 函数接收一个组件和配置对象,把组件实例化并挂到指定 DOM 节点上:
import { mount } from 'svelte';
import App from './App.svelte';
const app = mount(App, {
target: document.querySelector('#app'),
props: { some: 'property' }
});
两个关键参数:
target:组件要挂到哪个 DOM 元素上(必填)props:传给组件的属性(可选)
mount 返回的是组件实例对象,后续可以用它来卸载组件。
你可以在一个页面上挂载多个组件,也可以在应用运行时动态挂载。比如做一个 tooltip 组件,鼠标 hover 到某个元素时才挂上去:
import { mount, unmount } from 'svelte';
import Tooltip from './Tooltip.svelte';
let tooltipInstance;
function showTooltip(target, text) {
tooltipInstance = mount(Tooltip, {
target: document.body,
props: { text, anchor: target }
});
}
function hideTooltip() {
if (tooltipInstance) {
unmount(tooltipInstance);
tooltipInstance = null;
}
}
unmount:卸载组件
unmount 把之前用 mount 或 hydrate 挂载的组件从 DOM 中移除:
import { mount, unmount } from 'svelte';
import App from './App.svelte';
const app = mount(App, { target: document.body });
// 之后某个时机卸载
unmount(app);
如果你希望组件卸载时播放过渡动画(而不是瞬间消失),可以加上 outro 选项:
unmount(app, { outro: true });
加了 outro: true 后,unmount 会返回一个 Promise,等过渡动画播完才 resolve。不加就是同步移除。
更新 props
Svelte 4 里你可以用 component.$set({ count: 1 }) 来更新 props。Svelte 5 的做法不同,你需要把 props 本身变成响应式状态:
import { mount } from 'svelte';
import App from './App.svelte';
let props = $state({ count: 0 });
const app = mount(App, { props });
// 之后更新 props,组件会自动响应
props.count = 5;
这里用到了 $state 让 props 对象变成响应式的。修改 props.count 后,组件内部会自动更新。这比 Svelte 4 的 $set 优雅得多。
Tip
$state只能在.svelte或.svelte.js文件里使用。如果你的入口是普通.js文件,把文件名改成.svelte.js就行。
hydrate:水合渲染
hydrate 和 mount 很像,区别在于它不会从头创建 DOM,而是复用服务端渲染好的 HTML,只给现有 DOM 添加交互能力:
import { hydrate } from 'svelte';
import App from './App.svelte';
const app = hydrate(App, {
target: document.querySelector('#app'),
props: { some: 'property' }
});
水合的过程就像给一栋建好的房子接通水电——结构已经有了,只需要让它”活”起来。
典型的水合流程是:
- 服务器用
render把组件渲染成 HTML 字符串 - 浏览器收到 HTML 并直接显示(用户马上能看到内容)
- 浏览器加载 JS 后,用
hydrate接管这堆 HTML
Note和
mount一样,hydrate期间副作用($effect、onMount等)不会立即执行。如果你在测试中需要强制执行,可以调用flushSync()。
render:服务端渲染
render 只在服务端可用,它把组件渲染成 HTML 字符串:
import { render } from 'svelte/server';
import App from './App.svelte';
const result = render(App, {
props: { some: 'property' }
});
result.body; // HTML 字符串,放进 <body>
result.head; // <head> 里的内容,如 <svelte:head> 标记
返回对象有两个属性:
| 属性 | 说明 |
|---|---|
body | 组件渲染出的 HTML,插入到 <body> 中 |
head | 组件中 <svelte:head> 的内容,插入到 <head> 中 |
Note
render从svelte/server导入,不是从svelte导入。它只在服务端有效,浏览器环境中不可用。
flushSync:强制刷新副作用
mount 和 hydrate 执行后,组件的副作用($effect、onMount 回调、action 函数)不会立刻运行。它们被排到一个队列里,等微任务执行时才批量处理。
如果你需要让副作用立刻执行(比如在测试中断言 DOM 状态),可以用 flushSync:
import { mount, flushSync } from 'svelte';
import App from './App.svelte';
const app = mount(App, { target: document.body });
flushSync(); // 强制执行所有排队的副作用
与 Svelte 4 对照
Svelte 4 用 new Component() 创建组件,Svelte 5 改成了函数式 API。对照表如下:
| 操作 | Svelte 4 | Svelte 5 |
|---|---|---|
| 创建并挂载 | new App({ target, props }) | mount(App, { target, props }) |
| 卸载 | app.$destroy() | unmount(app) |
| 更新 props | app.$set({ count: 1 }) | props.count = 1(props 用 $state 包裹) |
| 监听事件 | app.$on('event', fn) | 传回调 props |
| 服务端渲染 | App.render(props) | render(App, { props })(从 svelte/server) |
| 读取 props | app.prop(需 accessors: true) | 不支持,用 $props() 在组件内访问 |
Svelte 5 移除了 $set、$on、$destroy 这些实例方法,改为更纯粹的函数式调用。这让 API 更简洁,也更容易做类型推导和 tree-shaking。
Tip如果你在迁移旧项目,
new App()改成mount(App, ...)是最直观的变化。事件监听改用回调 props 是较大的改动,参考第 42 章迁移指南。
createComponent:先创建后挂载
createComponent 是 Svelte 5.56+ 的命令式 API,用于创建组件实例但不立即挂载。它返回一个包含 mount、destroy、$set、$on 等方法的对象,适合需要先准备再挂载的场景(如组件库、弹窗管理)。
import { createComponent } from 'svelte';
const comp = createComponent(App, {
props: { title: '弹窗标题' },
target: document.getElementById('modal')
});
// 后续可以手动挂载
comp.mount();
// 更新 props
comp.$set({ title: '新标题' });
// 监听事件
comp.$on('close', () => {
comp.destroy();
});
// 销毁
comp.destroy();
Tip
createComponent适合需要精细控制组件生命周期的场景,比如弹窗组件需要先创建实例、绑定事件,再决定何时挂载到 DOM。
命令式 API 速查表
| API | 来源 | 用途 | 返回值 |
|---|---|---|---|
mount | svelte | 在浏览器中挂载组件到 DOM | 组件实例 |
unmount | svelte | 从 DOM 移除组件 | Promise 或 void |
hydrate | svelte | 复用 SSR 的 HTML 并水合 | 组件实例 |
render | svelte/server | 服务端渲染为 HTML 字符串 | { body, head } |
flushSync | svelte | 强制执行排队中的副作用 | void |
本节回顾
mount(App, { target, props })在浏览器中挂载组件,替代 Svelte 4 的new App()unmount(app)卸载组件,加{ outro: true }可播放离场动画- 更新 props 需要用
$state包裹 props 对象,直接赋值即可触发更新 hydrate复用 SSR 输出的 HTML,给已有 DOM 添加交互render(从svelte/server导入)在服务端把组件渲染成 HTML 字符串flushSync()强制执行排队的副作用,测试场景常用