$inspect 与调试技巧
本教程共 50 篇 · 第 36 篇 · 更新于 2026-08-05 · 约 6 分钟阅读
36. $inspect 与调试技巧
本节目标:学会用
$inspectrune 实时追踪响应式状态变化,掌握$inspect().with()和$inspect.trace()的高级用法,了解编译器警告/错误的处理和常用调试手段。
$inspect 基础
调试时你最常做的事就是 console.log。但响应式状态变化时,你往往想知道”每次变化后的值是多少”,手动写 console.log 很难追上。
Svelte 5 提供了 $inspect rune,它相当于会自动重跑的 console.log——只要你传给它的值变了,它就自动打印一次:
<script>
let count = $state(0);
let message = $state('hello');
// count 或 message 变化时自动打印
$inspect(count, message);
</script>
<button onclick={() => count++}>加 1</button>
<input bind:value={message} />
点击按钮时,控制台会输出 count 的新值;输入文字时,会输出 message 的新值。你不用手动在事件处理器里写 log。
Note
$inspect只在开发环境生效。生产构建时它会被编译成空操作(noop),不会影响性能。
深度追踪
$inspect 会深度追踪响应式状态。这意味着你修改对象或数组内部的属性,它也能捕获到:
<script>
let user = $state({ name: '张三', age: 25 });
$inspect(user);
function growUp() {
user.age++; // 修改内部属性,$inspect 也会触发
}
</script>
<button onclick={growUp}>长大一岁</button>
每次点击按钮,user 对象的 age 变化都会触发 $inspect 打印,即使你改的是对象内部属性而不是整个变量。
$inspect().with():自定义处理
默认情况下 $inspect 用 console.log 输出。如果你想自定义处理逻辑(比如触发断点、发送到远程日志),用 .with() 方法:
<script>
let count = $state(0);
$inspect(count).with((type, value) => {
// type 是 'init'(首次)或 'update'(变化时)
if (type === 'update') {
console.trace(`count 变成了 ${value}`);
}
});
</script>
<button onclick={() => count++}>加 1</button>
回调函数的第一个参数是 "init" 或 "update",表示是首次执行还是状态变化触发。后续参数就是你传给 $inspect 的值。
Tip在
.with()回调里写debugger语句,可以在状态变化时自动暂停代码执行,方便你在 DevTools 里检查调用栈和局部变量。
$inspect.trace():追踪函数重跑
$inspect.trace() 是 5.14 引入的调试工具。它用于追踪某个函数的重复执行,告诉你哪些响应式状态导致了函数重新运行:
<script>
import { doSomeWork } from './utils.svelte.js';
let theme = $state('light');
let data = $state([]);
$effect(() => {
$inspect.trace(); // 必须是函数体的第一条语句
doSomeWork(theme, data);
});
</script>
当这个 $effect 因为某个状态变化而重新执行时,控制台会打印出具体是 theme 还是 data 触发的重跑。这在排查”为什么我的 effect 总是不停重跑”时特别有用。
$inspect.trace() 接受一个可选的标签参数:
$inspect.trace('我的副作用'); // 控制台输出时带上标签
Note
$inspect.trace()必须是函数体的第一条语句,否则不会生效。它只在开发环境有效。
svelte-ignore 注释
Svelte 编译器会在编译时检查你的代码,发现潜在问题就发警告。最常见的是无障碍(a11y)警告,比如:
<!-- A11y: Avoid using autofocus -->
<input autofocus />
有时候你确实需要这么做,警告是误报。这时用 svelte-ignore 注释来屏蔽:
<!-- svelte-ignore a11y_autofocus -->
<input autofocus />
注意事项:
- 注释必须放在触发警告的那行代码上方
- 可以同时屏蔽多条规则,逗号分隔
- 可以在规则后加括号写说明
<!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_static_element_interactions (自定义交互元素) -->
<div onclick={handleClick}>...</div>
Tip不要滥用
svelte-ignore。每个被忽略的警告都可能是真实的无障碍问题。只有确认是误报时才使用。
编译器警告与错误
Svelte 编译过程会产生两类消息:
编译器警告(warning):代码能编译通过,但可能有问题。最常见的是 a11y 相关的警告(如 a11y_autofocus、a11y_click_events_have_key_events、a11y_missing_attribute 等)。其他还有 unused_export_let(导出的 prop 未使用)等。
编译器错误(error):代码无法编译。比如重复的属性名、无效的事件处理器、animate: 指令使用位置不对等:
<!-- 错误:事件属性必须是表达式,不能是字符串 -->
<button onclick="handleClick()">点击</button>
<!-- 正确 -->
<button onclick={handleClick}>点击</button>
编译错误会直接阻止构建,你必须修复才能继续。
运行时警告与错误
除了编译期,Svelte 在运行时也会报错和警告。常见的运行时错误包括:
state_proxy_equality_mismatch:在Set/Map中使用$state代理对象导致相等性判断出错effect_update_depth_exceeded:$effect互相触发形成无限循环lifecycle_outside_component:在组件生命周期外调用了onMount等函数
运行时警告不会中断程序,但建议认真对待,它们往往指向潜在的 bug。
调试工具汇总
| 工具 | 用途 | 适用场景 |
|---|---|---|
$inspect(value) | 自动追踪状态变化 | 日常调试 |
$inspect(value).with(fn) | 自定义处理变化事件 | 断点、远程日志 |
$inspect.trace() | 追踪函数重跑原因 | 排查 effect 频繁重跑 |
flushSync() | 强制执行排队的副作用 | 测试中验证 DOM 状态 |
svelte-ignore | 屏蔽编译器警告 | 确认误报时 |
| VS Code 插件 | 语法高亮、类型检查、错误提示 | 日常开发 |
svelte-check | 命令行类型检查 | CI/CD 流程 |
Tip浏览器的 DevTools 也是调试利器。在 Sources 面板中你能看到 Svelte 编译后的代码,在 Elements 面板可以直接检查 DOM。配合
$inspect的自动追踪,调试体验相当顺畅。
本节回顾
$inspect(value)会自动追踪状态变化并打印,只在开发环境生效$inspect().with(fn)用自定义回调替代console.log,可用于触发断点$inspect.trace()追踪函数重跑原因,必须是函数体第一条语句<!-- svelte-ignore 规则名 -->可屏蔽误报警告,可写多条规则- 编译器错误会阻止构建,必须修复;警告可选择性忽略
- 运行时错误指向潜在的响应式 bug,需要认真排查