Svelte 组件文件结构
本教程共 50 篇 · 第 3 篇 · 更新于 2026-08-05 · 约 5 分钟阅读
3. Svelte 组件文件结构
本节目标:掌握 .svelte 文件的三段式结构,理解每种脚本标签的用途,学会用 .svelte.js 模块文件共享响应式逻辑。学完你能看懂并编写规范的 Svelte 组件。
三段式结构
Svelte 组件写在 .svelte 文件里,本质是 HTML 的超集。一个完整的组件包含三个部分:
<!--- file: MyComponent.svelte --->
<script module>
// 模块级逻辑(不常用)
</script>
<script>
// 实例级逻辑(常用)
</script>
<!-- 标记(HTML 模板) -->
<style>
/* 样式 */
</style>
三个部分都是可选的。一个只有模板的 .svelte 文件也是合法组件。
<script> 实例脚本
<script> 标签里的代码在每个组件实例创建时执行一次。这里声明的变量可以在模板中直接使用:
<script>
let name = 'Svelte';
let count = 0;
function handleClick() {
count++;
}
</script>
<h1>Hello {name}!</h1>
<button onclick={handleClick}>点击次数:{count}</button>
在 <script> 中,除了普通 JavaScript,你还可以使用 Runes(如 $state、$derived、$props 等)来声明响应式状态和组件属性。Runes 是 Svelte 5 的核心特性,后面几章会详细讲。
用 TypeScript
加上 lang="ts" 属性,就能在脚本里写 TypeScript:
<script lang="ts">
let count: number = $state(0);
let name: string = 'Svelte';
function add(a: number, b: number): number {
return a + b;
}
</script>
Tip推荐使用 TypeScript。类型提示能在编码时帮你发现错误,Svelte 的 VS Code 插件对此有完整支持。
<script module> 模块脚本
<script module> 标签里的代码在模块首次加载时执行一次,而不是每个组件实例都执行。所有实例共享同一份模块级变量。
<script module>
let total = 0;
// 可以 export,外部文件能导入
export function getTotal() {
return total;
}
</script>
<script>
total += 1;
console.log(`这个组件已被实例化 ${total} 次`);
</script>
这里有两个要点:
- 模块脚本的变量能被实例脚本访问,反过来不行
- 模块脚本里可以
export,导出的内容能被其他文件import
Note在 Svelte 4 中,模块脚本的写法是
<script context="module">。Svelte 5 改成了<script module>,更简洁。实际开发中模块脚本用得不多,大多数逻辑放在实例脚本里就行。
<style> 样式
<style> 标签里的 CSS 默认是作用域隔离的(scoped),只影响当前组件的元素:
<p>这段文字是棕色的</p>
<style>
p {
/* 只会影响当前组件的 <p> */
color: burlywood;
}
</style>
Svelte 编译时会自动给元素加上唯一的 class 哈希值,确保样式不泄漏到其他组件。
模板标记
<script> 和 <style> 之间的部分就是模板,写的是标准 HTML 加上 Svelte 的扩展语法:
<div class="card">
<h2>{title}</h2>
<p>{description}</p>
</div>
模板里可以用 {} 插入 JavaScript 表达式,可以用 {#if}、{#each} 等控制流标签。这些会在后面的章节详细讲。
组件命名约定
Svelte 组件文件用大驼峰命名(PascalCase),如 MyComponent.svelte、UserCard.svelte。
在模板中使用组件时,标签名首字母必须大写,这样 Svelte 才能区分它是组件而不是普通 HTML 标签:
<script>
import Widget from './Widget.svelte';
import myStuff from './myStuff.js'; // 普通模块
</script>
<div>
<Widget /> <!-- 大写开头 = 组件 -->
<my.stuff /> <!-- 点号开头 = 组件 -->
<div></div> <!-- 小写开头 = HTML 元素 -->
</div>
Tip约定俗成:HTML 元素全小写(
div、span),Svelte 组件首字母大写(Widget、UserCard)。这条规则帮你一眼区分组件和原生标签。
.svelte.js / .svelte.ts 模块文件
除了 .svelte 文件,Svelte 5 还支持 .svelte.js 和 .svelte.ts 文件。它们和普通的 .js/.ts 模块一样,但有一个关键区别:可以在里面使用 Runes。
这让你能提取可复用的响应式逻辑,在多个组件间共享:
//--- file: counter.svelte.ts ---
export function createCounter(initial: number = 0) {
let count = $state(initial);
function increment() {
count++;
}
function reset() {
count = initial;
}
return {
get count() {
return count;
},
increment,
reset
};
}
在组件中使用:
<script lang="ts">
import { createCounter } from './counter.svelte.ts';
const counter = createCounter(10);
</script>
<button onclick={counter.increment}>
计数:{counter.count}
</button>
Note
.svelte.js文件是 Svelte 5 新增的概念,在 Svelte 4 中不存在。它是实现”组合式逻辑复用”的关键工具,类似于 Vue 3 的 Composables 或 React 的自定义 Hooks。
三种文件对比
| 文件类型 | 用途 | 能用 Runes | 能写模板 |
|---|---|---|---|
.svelte | 组件 | 能 | 能 |
.svelte.js / .svelte.ts | 响应式逻辑模块 | 能 | 不能 |
.js / .ts | 普通模块 | 不能 | 不能 |
本节回顾
.svelte文件是三段式结构:<script>(逻辑)、模板(HTML)、<style>(样式)<script>是实例级,每次组件创建时执行;<script module>是模块级,只执行一次- 加
lang="ts"即可使用 TypeScript <style>默认 scoped,样式只作用于当前组件- 组件文件用大驼峰命名,使用时首字母大写区分于 HTML 元素
.svelte.js/.svelte.ts模块文件支持 Runes,用于共享响应式逻辑