v-html 是 vue 中唯一能直接解析 html 字符串为 dom 的指令,适合可信富文本,但存在 xss 风险;需配合 dompurify 净化、后端严格过滤,并避免与 v-if 等指令共用。

v-html 是 Vue 中唯一能直接把 HTML 字符串解析并渲染成真实 DOM 的指令,但它不做转义、不校验、不编译——传进去什么,浏览器就执行什么。所以它适合渲染可信的富文本,但绝不能裸奔用在用户输入或 CMS 输出上。
基础用法:把字符串当 HTML 插入
只需绑定一个含 HTML 标签的字符串变量即可:
- 在 data 或 ref/computed 中定义 HTML 字符串,例如
'<p><strong>加粗</strong> + @#@#@#@#@#@#@#@#@#@0</p>' - 在模板中用
v-html="variableName"绑定到普通元素(如<div>、<code><span></span>),不能用于组件根节点 - 注意:v-html 会完全替换元素的 innerHTML,原有子节点(包括插槽、文本、其他指令)都会被丢弃
- 不能和
v-if、v-for、v-model等指令共存于同一元素,否则报错或行为异常 - 不会响应 Vue 模板语法:
{{ }}、v-on:click、组件标签等在里面全部失效,纯静态 HTML - 数据更新后,DOM 不会自动重渲染——必须重新赋值整个字符串,Vue 才会触发 innerHTML 更新
- 服务端渲染(SSR)时,v-html 内容无法被水合(hydration),容易导致客户端和服务端 DOM 不一致
- 前端仅作辅助:用
DOMPurify在 computed 或 setup 中净化,例如computed(() => DOMPurify.sanitize(dirtyHtml)) - 后端才是主防线:Python 用
bleach,Node.js 用sanitize-html,严格移除<script></script>、onerror、javascript:、data:等高危内容 - 优先考虑替代方案:比如用 Markdown 解析为 AST,再用 Vue 组件递归渲染;或只支持有限格式(换行、
<strong></strong>、<a></a>),用正则+白名单转义 - 定义数据:
const msgs = ref(['普通消息', '<b>重要提醒</b>', '<p><img src="logo.png"></p>']) - 模板中循环渲染:
<div v-for="(msg, i) in msgs" :key="i" v-html="msg"></div> - 若需样式隔离,可包裹在带 scoped CSS 的容器里,或用
iframe沙箱(较重,慎用)
常见陷阱与限制
v-html 看似简单,但有几条硬性约束必须遵守:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
安全处理富文本的必要步骤
富文本来自编辑器、后台或第三方接口时,必须清洗,否则极易触发 XSS:
实用示例:渲染混合消息列表
假设你有一组消息,有的纯文本,有的带 HTML 格式:










