@html、@const 与 @debug
本教程共 50 篇 · 第 16 篇 · 更新于 2026-08-05 · 约 5 分钟阅读
16. @html、@const 与 @debug
本节目标:掌握 {@html}、{@const}、{@debug} 三个特殊模板标签的用法和注意事项。学完你能在模板中安全渲染 HTML、声明局部常量、调试响应式状态。
{@html}:渲染原始 HTML
基本用法
默认情况下,{} 插值会自动转义 HTML 标签。如果你需要渲染原始 HTML,用 {@html}:
<script>
let content = '<strong>加粗文字</strong>';
</script>
<!-- 转义:显示原始标签 -->
<p>{content}</p>
<!-- 输出:<strong>加粗文字</strong> -->
<!-- 原始 HTML:渲染为加粗 -->
<p>{@html content}</p>
<!-- 输出:<strong>加粗文字</strong>(文字加粗显示) -->
安全警告
Warning
{@html}不会对内容做任何转义。如果你渲染用户输入的 HTML,可能导致 XSS 攻击。永远不要用{@html}渲染不可信的内容。
<script>
// 假设这是用户提交的内容
let userInput = '<img src=x onerror="alert(\'XSS攻击\')">';
</script>
<!-- ❌ 危险!可能执行恶意代码 -->
<div>{@html userInput}</div>
<!-- ✅ 安全:普通插值会转义 -->
<div>{userInput}</div>
如果确实需要渲染用户提供的 HTML,先用专门的库(如 DOMPurify)做净化:
<script>
import DOMPurify from 'dompurify';
let userInput = '<script>alert("xss")<\/script>文字内容';
let safe = $derived(DOMPurify.sanitize(userInput));
</script>
<div>{@html safe}</div>
样式限制
{@html} 渲染的内容对 Svelte 的 scoped 样式是「不可见」的。也就是说,组件 <style> 里的选择器不会作用到 {@html} 插入的元素上:
<!-- ❌ 不起作用:a 和 img 的样式不会应用到 @html 内容 -->
<article>
{@html content}
</article>
<style>
article {
a { color: hotpink }
img { width: 100% }
}
</style>
用 :global() 修饰符解决,把要穿透作用域的选择器包进括号:
<!-- ✅ 用 :global() 让样式穿透到 @html 渲染的内容 -->
<style>
article :global(a) { color: hotpink }
article :global(img) { width: 100% }
</style>
Note
{@html}渲染的内容必须是完整的 HTML 片段。不能把标签拆开写(如{@html '<div>'}+ 内容 +{@html '</div>'}),也不能在里面写 Svelte 语法。
{@const}:声明局部常量
基本用法
{@const} 在模板中声明一个局部常量,只能在块内部使用:
<script>
let boxes = [
{ width: 10, height: 10 },
{ width: 15, height: 20 },
{ width: 5, height: 8 }
];
</script>
{#each boxes as box}
{@const area = box.width * box.height}
<p>{box.width} × {box.height} = {area}</p>
{/each}
输出:
10 × 10 = 100
15 × 20 = 300
5 × 8 = 40
使用位置限制
{@const} 只能作为以下内容的直接子级:
{#if ...}块{#each ...}块{#snippet ...}块<Component />标签<svelte:boundary>
<!-- ✅ 在 each 块中 -->
{#each items as item}
{@const total = item.price * item.qty}
<p>{total}</p>
{/each}
<!-- ✅ 在 if 块中 -->
{#if condition}
{@const label = '条件为真'}
<p>{label}</p>
{/if}
<!-- ✅ 在组件标签中 -->
<div>
{@const className = isActive ? 'active' : 'inactive'}
<ChildComponent class={className} />
</div>
<!-- ❌ 不能在顶层直接使用 -->
{@const x = 1} <!-- 编译错误 -->
Tip
{@const}适合在模板里做简单的中间计算,避免在<script>中写一堆$derived。如果计算逻辑复杂或需要响应式更新,还是应该用$derived。
与声明标签的关系
Note在 Svelte 5.56+ 中,
{@const}被视为旧语法。推荐使用声明标签{const x = value}替代。下一章会详细介绍声明标签。目前两者都能使用,{const}是{@const}的进化版,使用位置更灵活。
{@debug}:调试断点
基本用法
{@debug} 是比 console.log 更强的调试工具。它在指定变量变化时自动打印值,并在开发者工具打开时暂停执行:
<script>
let user = $state({
firstname: 'Ada',
lastname: 'Lovelace'
});
</script>
{@debug user}
<h1>Hello {user.firstname}!</h1>
<input bind:value={user.firstname} />
每次 user 变化时(比如在输入框中输入),控制台会打印 user 的当前值,并触发 debugger 断点。
语法规则
{@debug} 接受逗号分隔的变量名列表,不能是表达式:
<!-- ✅ 合法 -->
{@debug user}
{@debug user1, user2, user3}
{@debug} <!-- 无参数:任何状态变化都触发 -->
<!-- ❌ 编译错误 -->
{@debug user.firstname} <!-- 不能是属性访问 -->
{@debug myArray[0]} <!-- 不能是数组索引 -->
{@debug !isReady} <!-- 不能是表达式 -->
{@debug typeof user === 'object'} <!-- 不能是表达式 -->
Note
{@debug}是开发调试工具,生产构建时会自动移除,不影响线上性能。建议在排查响应式问题时临时使用,不要长期留在代码中。
调试 vs console.log
| 对比项 | {@debug} | console.log |
|---|---|---|
| 触发时机 | 变量变化时自动触发 | 只在执行时打印一次 |
| 断点 | 自动触发 debugger | 无 |
| 表达式支持 | 只支持变量名 | 任意表达式 |
| 适用位置 | 模板中 | <script> 中 |
| 适合场景 | 排查响应式更新问题 | 一次性日志 |
三个标签对比
| 标签 | 作用 | 生产环境 |
|---|---|---|
{@html} | 渲染原始 HTML | 保留 |
{@const} | 声明局部常量 | 保留(推荐用 {const} 替代) |
{@debug} | 调试断点 | 自动移除 |
本节回顾
{@html 内容}渲染原始 HTML,但有 XSS 风险,不可信内容必须先净化{@html}内容不受 scoped 样式影响,需用:global()穿透{@const 变量 = 值}在块内声明局部常量,简化中间计算{@const}只能用在 if/each/snippet/组件标签内部{@debug 变量}在变量变化时打印并暂停,只接受变量名不接受表达式{@debug}生产环境自动移除,适合临时调试- Svelte 5.56+ 推荐用声明标签
{const}替代{@const}