在 Vue.js 中,v-text 和 v-html 都是用于数据绑定的指令,但它们在处理内容和安全性上有显著区别。以下是详细说明和注意事项:
1. v-text 指令
作用:
将数据以 纯文本 形式插入到元素中(相当于设置元素的 textContent 属性)。
语法:
<div v-text="message"></div>
等价于:
<div>{{ message }}</div>
特点:
- 自动转义 HTML 标签(例如
<script>会变成文本<script>) - 防止 XSS 攻击(跨站脚本攻击)
- 覆盖元素内原有的所有内容
示例:
<template>
<div>
<p v-text="rawContent"></p>
</div>
</template>
<script>
export default {
data() {
return {
rawContent: '<strong>Hello</strong> World!'
};
}
};
</script>
渲染结果:
<p><strong>Hello</strong> World!</p>
页面上显示:
<strong>Hello</strong> World!
2. v-html 指令
作用:
将数据作为 HTML 代码 解析并插入到元素中(相当于设置元素的 innerHTML 属性)。
语法:
<div v-html="htmlContent"></div>
特点:
- 解析并渲染 HTML 标签
- 不会转义内容,存在安全风险
- 覆盖元素内原有的所有内容
示例:
<template>
<div>
<p v-html="rawContent"></p>
</div>
</template>
<script>
export default {
data() {
return {
rawContent: '<strong>Hello</strong> World!'
};
}
};
</script>
渲染结果:
<p><strong>Hello</strong> World!</p>
页面上显示:
Hello World!
⚠️ 关键注意事项
1. 安全性风险(v-html)
- XSS 攻击:
v-html会执行传入的任意 HTML 代码,如果内容来自用户输入(如评论、富文本编辑器),攻击者可能注入恶意脚本(如<script>alert(1)</script>)。 - 解决方案:
- 仅对 完全信任的内容 使用
v-html。 - 对动态内容使用 HTML 过滤库(如
DOMPurify):<div v-html="sanitizedContent"></div>import DOMPurify from 'dompurify'; // ... computed: { sanitizedContent() { return DOMPurify.sanitize(this.untrustedContent); } }
- 仅对 完全信任的内容 使用
2. 作用域问题
- v-html 不编译 Vue 模板:
通过v-html插入的内容中的 Vue 指令(如{{ }}、v-model)不会被解析。
3. 样式作用域(Scoped CSS)
- Scoped CSS 不生效:
通过v-html动态添加的 HTML 内容,不受当前组件的 Scoped CSS 影响(因为不在 Vue 的编译流程中)。 - 解决方案:
- 使用全局 CSS
- 或深度选择器 (
:deep()in Vue 3):/* Vue 3 */ :deep(.dynamic-content) { color: red; }
4. 覆盖原有内容
- 两者都会覆盖:
使用v-text或v-html的元素内部原有内容会被完全替换。
5. 性能差异
- v-html 更耗性能:
修改innerHTML会触发浏览器的重解析,比textContent(v-text)开销更大。
使用建议
| 场景 | 推荐指令 | 原因 |
|---|---|---|
| 纯文本内容 | v-text | 安全、高效 |
| 渲染可信的 HTML(如后台配置) | v-html | 需确保内容安全 |
| 用户输入的内容 | 避免使用 | 必须过滤或使用纯文本渲染 |
代码对比总结
| 指令 | 等价操作 | HTML 转义 | XSS 风险 | 性能 |
|---|---|---|---|---|
v-text | textContent | ✅ 自动转义 | ❌ 无 | ⭐️⭐️⭐️ 高 |
v-html | innerHTML | ❌ 不转义 | ✅ 有 | ⭐️⭐️ 中 |
始终优先使用 v-text 或插值表达式 ({{ }}),仅在必要时谨慎使用 v-html 并严格过滤内容!
201

被折叠的 条评论
为什么被折叠?



