v-html 是 Vue 中唯一直接渲染 HTML 字符串的指令,但不转义、不校验、不编译,存在 XSS 风险;禁用在组件根元素、不响应数据变化、不可与其他指令共用;安全做法为优先避免使用、前端用 DOMPurify 净化、后端严格清洗,并推荐 Markdown/AST 替代方案。

v-html 是 Vue 中唯一能直接把字符串当 HTML 解析并渲染的指令,但它不转义、不校验、不编译,内容会原样塞进 innerHTML——这意味着你传什么,浏览器就执行什么。用对了很高效,用错了可能立刻被 XSS 攻击。
v-html 的基本行为和限制
它只做一件事:把绑定的字符串赋给元素的 innerHTML 属性。所以:
- 不会解析其中的 {{ }}、v-if、组件标签等 Vue 语法
- 不响应数据变化——改了原始值,DOM 不自动更新,除非重新赋值
- 不能和 v-model、v-if、v-for 等指令写在同一元素上
- 不能用于组件的根元素(会报错)
- 服务端渲染(SSR)时,v-html 渲染的内容不会被水合(hydration)接管,容易出现 DOM 不一致
为什么不能直接用用户输入或 CMS 输出?
富文本编辑器、评论区、后台管理界面导出的 HTML,表面看是排版,实则可能藏有:
- <script>alert('xss')</script>
- 点击
这些代码在 v-html 插入后会被浏览器真实执行。Vue 不会帮你过滤,也不做沙箱隔离。
安全使用的三个落地做法
别依赖“这个来源应该可信”,而要默认所有动态 HTML 都需清洗:
- 优先不用:标题用 {{ title }},简单格式用正则转义(如 \*\*(.*?)\*\* → $1),结构化内容转 JSON AST + 组件递归渲染
-
前端净化只是辅助:npm install dompurify 后,在 computed 或 setup 中调用:
const safeHtml = computed(() => DOMPurify.sanitize(rawHtml)),再绑定到 v-html - 后端清洗才是核心防线:用 bleach(Python)、sanitize-html(Node)等成熟库,严格移除 script、onxxx 事件、javascript: 协议、data: 协议等高危内容
替代方案比 v-html 更可控
多数业务场景其实不需要完整 HTML 支持:
- 仅需换行、加粗、链接:用 text.replace(/\n/g, '
').replace(/\*\*(.*?)\*\*/g, '$1') + v-html,限定标签白名单 - 需要富文本能力:把 Markdown 或自定义 schema 解析成 JSON AST,用 Vue 组件逐节点渲染(比如
文本 → 文本) - 静态文档页等完全可信内容:可用 v-html,但仍建议过一遍 DOMPurify,防配置错误或模板注入漏网
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











