首页 / Svelte 5 入门教程 / <svelte:boundary> 错误边界

Svelte 5 入门教程

<svelte:boundary> 错误边界

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

SvelteSvelte 5错误边界svelte:boundary错误处理

本节目标:学会用 svelte:boundary 隔离错误,掌握 failed 和 pending snippet 的用法,理解错误恢复机制和 onerror 回调。

什么是错误边界

组件渲染时可能抛出错误——访问了 undefined 的属性、数据格式不对等等。如果没有错误边界,一个小组件的崩溃会让整个页面白屏。

错误边界就像给组件装了”防火墙”——里面的组件崩了,外面不受影响,还能显示一个友好的提示界面。

打个比方,错误边界就像大楼里的防火门。某个房间着火了,防火门自动关闭,火势不会蔓延到其他房间。

<svelte:boundary> 是 Svelte 5.3.0 新增的功能。

基本用法

错误边界需要配合 failed snippet 使用。当内部组件出错时,failed snippet 会替代原来的内容显示。

<script>
	import FlakyComponent from './FlakyComponent.svelte';
</script>

<svelte:boundary>
	<FlakyComponent />

	{#snippet failed(error, reset)}
		<div style="padding: 20px; background: #fee; border: 1px solid #f00;">
			<p>出错了:{error.message}</p>
			<button onclick={reset}>重试</button>
		</div>
	{/snippet}
</svelte:boundary>

failed snippet 接收两个参数:

  • error:抛出的错误对象
  • reset:一个函数,调用后会重新渲染边界内的内容
Note

错误边界只会捕获渲染过程和 effect 执行时的错误。事件处理器里、setTimeout 回调里、异步操作后的错误不会被捕获——这些需要你用 try/catch 自己处理。

pending snippet

pending snippet 在边界首次创建时显示,直到内部的所有 await 表达式都解析完毕。

<script>
	async function delayed(data) {
		await new Promise(r => setTimeout(r, 1000));
		return data;
	}
</script>

<svelte:boundary>
	<p>{await delayed('hello!')}</p>

	{#snippet pending()}
		<p>加载中...</p>
	{/snippet}
</svelte:boundary>

页面打开时先显示”加载中…”,一秒后变成”hello!”。

Note

pending snippet 只在边界首次创建时显示,后续的异步更新不会触发。如果你需要追踪后续的异步状态,可以用 $effect.pending()

onerror 回调

除了 failed snippet,你还可以提供 onerror 回调函数。它接收同样的 errorreset 参数,但不会替代内容显示——适合用来上报错误。

<script>
	function reportError(error) {
		// 把错误发送到错误监控服务
		fetch('/api/errors', {
			method: 'POST',
			body: JSON.stringify({ message: error.message, stack: error.stack })
		});
	}
</script>

<svelte:boundary onerror={(error) => reportError(error)}>
	<FlakyComponent />

	{#snippet failed(error, reset)}
		<p>出了点问题,工程师正在抢修</p>
		<button onclick={reset}>重试</button>
	{/snippet}
</svelte:boundary>

在外部处理错误

有时候你想在边界外面控制错误状态。可以把 errorreset 存到状态变量中。

<script>
	let error = $state(null);
	let resetFn = $state(() => {});

	function onerror(e, reset) {
		error = e;
		resetFn = reset;
	}
</script>

<svelte:boundary {onerror}>
	<FlakyComponent />
</svelte:boundary>

{#if error}
	<div>
		<p>错误:{error.message}</p>
		<button onclick={() => {
			error = null;
			resetFn();
		}}>
			重试
		</button>
	</div>
{/if}

错误恢复

reset 函数是错误恢复的关键。调用它会重新渲染边界内的所有内容。

<script>
	let data = $state({ value: 42 });
	let renderCount = $state(0);

	function breakIt() {
		// 故意制造错误
		data = undefined;
	}
</script>

<svelte:boundary>
	<button onclick={breakIt}>制造错误</button>

	<!-- 访问 undefined 的 value 属性会抛错 -->
	<p>值:{data.value}</p>

	{#snippet failed(error, reset)}
		<div>
			<p>崩溃了!{error.message}</p>
			<button onclick={() => {
				// 修复数据后重置
				data = { value: 0 };
				reset();
			}}>
				修复并重试
			</button>
		</div>
	{/snippet}
</svelte:boundary>
Tip

reset 只是重新渲染组件。如果导致错误的数据没有被修复,重试后还是会报错。调用 reset 前先修复数据源。

嵌套错误边界

错误边界可以嵌套。内部的边界捕获错误后,外部边界不会收到这个错误。如果内部边界没有 failed snippet 或 onerror,错误会冒泡到外部边界。

<svelte:boundary>
	<!-- 外层错误边界 -->
	<p>外层内容</p>

	<svelte:boundary>
		<!-- 内层错误边界 -->
		<FlakyComponent />

		{#snippet failed(error, reset)}
			<p>内层捕获:{error.message}</p>
			<button onclick={reset}>内层重试</button>
		{/snippet}
	</svelte:boundary>

	{#snippet failed(error, reset)}
		<p>外层捕获:{error.message}</p>
		<button onclick={reset}>外层重试</button>
	{/snippet}
</svelte:boundary>
Note

如果 onerror 函数内部抛出错误(或重新抛出原始错误),这个错误会被父级错误边界处理。

实战:带加载和错误的异步组件

<script>
	let userId = $state(1);

	async function fetchUser(id) {
		const res = await fetch(`/api/users/${id}`);
		if (!res.ok) throw new Error('用户不存在');
		return res.json();
	}
</script>

<svelte:boundary>
	<div>
		<button onclick={() => userId += 1}>下一个用户</button>

		<div>
			<h3>用户信息</h3>
			<p>姓名:{(await fetchUser(userId)).name}</p>
		</div>
	</div>

	{#snippet pending()}
		<p>正在加载用户数据...</p>
	{/snippet}

	{#snippet failed(error, reset)}
		<div style="color: red;">
			<p>加载失败:{error.message}</p>
			<button onclick={reset}>重试</button>
		</div>
	{/snippet}
</svelte:boundary>

本节回顾

  • <svelte:boundary> 是 Svelte 5 的错误边界,隔离组件崩溃,防止整页白屏
  • failed snippet 在出错时显示,接收 errorreset 两个参数
  • pending snippet 在首次加载时显示,直到 await 表达式解析完毕
  • onerror 回调用于错误上报,不会替代内容显示
  • reset() 重新渲染边界内容,但需要先修复导致错误的数据
  • 错误边界可以嵌套,未处理的错误会冒泡到父级边界
  • 事件处理器和异步回调中的错误不会被边界捕获