You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue插槽渲染对象内HTML字符串失效,不使用v-html如何解决?

你当前使用双大括号{{ }}插值时,Vue默认会对内容做HTML转义,核心目的就是防止XSS攻击,所以所有HTML标签都会被当成普通字符串渲染。
要渲染HTML结构必然需要用到解析HTML的能力,你不想直接用v-html本质是怕不可信内容带来的XSS风险,所以正确的做法是先对CMS返回的HTML内容做XSS安全过滤,再通过v-html渲染,这也是目前业界的通用方案,不存在完全规避v-html还能解析HTML的原生Vue能力。

方案1:使用成熟的XSS过滤库处理后再渲染(推荐)

最常用的是DOMPurify,它会自动清理HTML字符串中的所有危险代码,只保留安全的标签和属性,使用方式:

  • 安装依赖
npm install dompurify
# 或者
yarn add dompurify
  • 在组件中使用
<template #content>
  <div v-html="sanitizedContent(item.content)"></div>
</template>

<script setup>
import DOMPurify from 'dompurify'

const sanitizedContent = (content) => {
  return DOMPurify.sanitize(content)
}
</script>

这个方案经过大量生产场景验证,安全性有保障,开发成本极低。

方案2:自定义白名单过滤(适合轻量场景)

如果你的场景只需要支持非常有限的HTML标签(比如仅允许<p>、<h2>、<ul>、<li>、<strong>这些基础标签),不想引入第三方依赖,可以自己实现一个简单的白名单过滤函数:

// 允许的标签白名单
const allowedTags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'strong', 'em', 'span']
// 允许的属性白名单
const allowedAttrs = ['class', 'style', 'href']

const sanitizeHtml = (html) => {
  // 简单实现,复杂场景还是推荐用DOMPurify
  return html.replace(/<(\/?)(\w+)([^>]*?)>/g, (match, closeTag, tag, attrs) => {
    tag = tag.toLowerCase()
    if (!allowedTags.includes(tag)) return ''
    // 过滤属性
    const safeAttrs = attrs.replace(/(\w+)\s*=\s*"([^"]*)"/g, (attrMatch, attrName, attrValue) => {
      attrName = attrName.toLowerCase()
      if (!allowedAttrs.includes(attrName)) return ''
      // 额外处理href的javascript:伪协议风险
      if (attrName === 'href' && attrValue.trim().startsWith('javascript:')) return ''
      return `${attrName}="${attrValue}"`
    })
    return `<${closeTag}${tag}${safeAttrs}>`
  })
}

过滤后的内容同样可以通过v-html安全渲染。

方案3:手动解析HTML生成VNode(适合自定义渲染场景)

如果你需要对HTML的渲染做更细粒度的控制(比如把<a>标签自动转换成Vue Router的<RouterLink>组件),可以使用HTML解析库把HTML字符串解析成AST,再通过Vue的h()渲染函数生成虚拟节点插入插槽,这种方案完全不需要用到v-html,但开发成本较高,适合复杂定制需求。


内容的提问来源于stack exchange,提问作者Udders

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 14:24:01