首页 / Svelte 5 入门教程 / 浏览器支持与最佳实践

Svelte 5 入门教程

浏览器支持与最佳实践

本教程共 50 篇 · 第 41 篇 · 更新于 2026-08-05 · 约 5 分钟阅读

SvelteSvelte 5浏览器兼容最佳实践无障碍

本节目标:了解 Svelte 5 的浏览器兼容范围,掌握代码组织的最佳实践、性能优化技巧和常见问题。

浏览器兼容性

Svelte 5 依赖一些现代浏览器 API。最低支持版本如下:

浏览器最低版本
Chrome87+
Firefox83+
Safari14+
Edge87+
iOS Safari14+
Android Chrome87+

这个表格只覆盖 Svelte 本身。SvelteKit 和其他库可能有更高的版本要求。

Note

个别 Svelte 特性需要更高的浏览器版本,比如某些过渡动画 API。如果你用了这些特性,需要额外检查兼容性。

$state 最佳实践

只在需要响应式的地方用 $state。不参与响应式更新的普通变量用 let 就行:

// 需要响应式 —— 用 $state
let count = $state(0);
let user = $state({ name: '张三' });

// 不需要响应式 —— 普通 let
let timeoutId = null;
let cache = new Map();

处理大型对象时,如果只整体替换不修改内部属性,用 $state.raw 省去代理开销:

// API 返回的数据通常只整体替换
let data = $state.raw([]);

async function loadData() {
	const res = await fetch('/api/data');
	data = await res.json(); // 整体替换,不做内部修改
}

$derived 而非 $effect

计算值用 $derived,不要用 $effect 加赋值来模拟(详见 §07 的对比)。$derived 更高效,Svelte 能更好地优化更新。表达式复杂时用 $derived.by

$effect 使用原则

$effect 是逃生舱口,尽量少用(§08 有详细说明)。优先考虑这些替代方案:

需求替代方案
同步外部库{@attach}
响应交互直接写事件处理器
调试日志$inspect
观察外部状态createSubscriber
Warning

不要在 $effect 里更新状态再被自己监听,这会导致无限循环。如果确实需要”状态联动”,考虑用 $derived

Props 最佳实践

把 props 当作会变化的值。依赖 props 的计算用 $derived

let { type } = $props();

// 正确 —— type 变了 color 也会更新
let color = $derived(type === 'danger' ? 'red' : 'green');

// 错误 —— type 变了 color 不会更新
let color = type === 'danger' ? 'red' : 'green';

不要修改 props(除非是 $bindable 的)。修改不属于自己组件的状态会导致警告。

事件处理

Svelte 5 中 on 开头的属性就是事件监听器:

<!-- 直接写函数 -->
<button onclick={() => { /* ... */ }}>点击</button>

<!-- 属性简写 -->
<button {onclick}>...</button>

<!-- 展开属性 -->
<button {...props}>...</button>

监听 windowdocument 事件用 <svelte:window><svelte:document>

<svelte:window onkeydown={handleKeydown} />
<svelte:document onvisibilitychange={handleVisibility} />

不要用 onMount$effect 来添加事件监听。

Each 块要加 key

遍历列表时加 key 能让 Svelte 精准地增删元素,而不是更新已有元素的 DOM:

<!-- 正确 —— 用唯一 id 做 key -->
{#each items as item (item.id)}
	<li>{item.name}</li>
{/each}

<!-- 避免 —— 用 index 做 key 会导致性能问题 -->
{#each items as item, i (i)}
	<li>{item.name}</li>
{/each}
Note

key 必须能唯一标识对象。不要用数组索引做 key,列表顺序变化时会导致渲染错乱。

CSS 最佳实践

JS 变量传给 CSS 用 style: 指令设置自定义属性:

<script>
	let columns = $state(3);
</script>

<div class="grid" style:--columns={columns}>
	<!-- ... -->
</div>

<style>
	.grid {
		display: grid;
		grid-template-columns: repeat(var(--columns), 1fr);
	}
</style>

父组件控制子组件样式,优先用 CSS 自定义属性传递:

<!-- Parent.svelte -->
<Child --color="red" />

<!-- Child.svelte -->
<h1>标题</h1>

<style>
	h1 {
		color: var(--color);
	}
</style>

Context 最佳实践

用 Context 而不是全局模块来共享状态。Context 天然限定在组件树范围内,SSR 时不会跨请求泄漏:

// 推荐:用 createContext
export const [getTheme, setTheme] = createContext<Theme>();
Tip

createContextsetContext/getContext 类型更安全。Svelte 5.40 起可用。

避免旧写法

新代码统一用 Runes 模式,避免使用已被替代的旧特性。完整的旧写法与新写法对照表见 §42,这里列出几个最常遇到的:

  • let count = 0let count = $state(0)
  • on:click={fn}onclick={fn}
  • <slot>{@render children()}
  • use:action{@attach}(Svelte 5.29+)

常见问题

Svelte 能处理大规模应用吗? 能。Svelte 是编译器,运行时极小,性能开销低。许多大型公司在生产环境使用。

有 UI 组件库吗? 有,Svelte 官方网站列了多个组件库和独立组件。

怎么格式化代码? 用 Prettier 配合 prettier-plugin-svelte 插件。

怎么写移动端应用? 把 SvelteKit SPA 用 Tauri 或 Capacitor 包装成移动应用,可访问相机、定位等原生能力。

有路由库吗? 官方路由是 SvelteKit,提供文件路由、SSR 和 HMR。也可以用第三方路由库。

怎么做热更新? SvelteKit 基于 Vite,内置 HMR 支持,不需要额外配置。

本节回顾

  • Svelte 5 支持 Chrome 87+、Firefox 83+、Safari 14+ 等现代浏览器
  • $state 只用于需要响应式的变量,大型只替换数据用 $state.raw
  • 计算值用 $derived 而非 $effect,effect 是最后的手段
  • Props 用 $derived 派生依赖值,不要直接修改非 $bindable 的 props
  • Each 块必须加唯一 key,不要用索引做 key
  • 新代码统一用 Runes,避免所有旧写法
  • 全局状态优先用 Context 而非模块级变量