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

Vue.js如何自动转义插槽内HTML代码适配highlight.js高亮?

解决Vue插槽中HTML代码自动转义并高亮的问题

嘿,我完全懂你现在的困扰——你做的这个highlight.js代码高亮组件,插槽里塞HTML代码的时候直接被渲染成页面元素了,手动转义<和>虽然能用,但每次都这么搞太麻烦了对吧?别担心,我给你几个靠谱的自动转义方案:

方案一:通过作用域插槽获取原始内容并自动转义

这是最灵活的方案,适合绝大多数场景,不管插槽里是静态还是动态内容都能处理。核心思路是在组件内部获取插槽的原始内容,转义后再传给highlight.js高亮:

组件代码改造

<script setup>
import hljs from 'highlight.js'
import 'highlight.js/styles/github.css' // 选你喜欢的高亮样式

const props = defineProps({
  language: {
    type: String,
    default: 'html' // 默认高亮HTML
  }
})

// 核心:HTML字符转义工具函数,覆盖所有特殊字符
const escapeHtml = (str) => {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;')
}

// 获取插槽的原始内容并转义
const getEscapedSlotContent = () => {
  const slots = useSlots()
  if (!slots.default) return ''

  let rawContent = ''
  // 遍历插槽的所有vnode,提取原始文本/HTML
  slots.default().forEach(vnode => {
    if (vnode.type === Text) {
      rawContent += vnode.children
    } else if (vnode.el) {
      rawContent += vnode.el.innerHTML
    }
  })

  return escapeHtml(rawContent)
}

// 组件挂载后初始化highlight.js高亮
onMounted(() => {
  const codeElement = document.querySelector('.highlight-code-block')
  if (codeElement) {
    hljs.highlightElement(codeElement)
  }
})
</script>

<template>
  <pre class="highlight-pre">
    <code 
      :class="`language-${language}`" 
      class="highlight-code-block"
      v-html="getEscapedSlotContent()"
    ></code>
  </pre>
</template>

使用方式

现在你直接在插槽里写原生HTML就行,不用手动转义:

<HighlightComponent language="html">
  <html>
    <head>
      <title>我的测试页面</title>
    </head>
    <body>
      <h1 style="color: red;">Hello World!</h1>
    </body>
  </html>
</HighlightComponent>

方案二:用v-pre指令快速处理静态代码

如果你的插槽内容只是纯静态的代码示例,不需要动态渲染,那可以用Vue的v-pre指令跳过编译,直接保留原始文本:

<HighlightComponent>
  <div v-pre>
    <html>
      <head></head>
      <body>
        <p>这是静态代码示例</p>
      </body>
    </html>
  </div>
</HighlightComponent>

注意:这个方案需要给代码外层套一个带v-pre的元素,组件里要确保只提取内部的代码内容,避免外层div标签被展示出来。

方案三:自定义全局过滤器简化转义

如果你在多个组件里都需要转义HTML,可以全局注册一个过滤器,复用转义逻辑:

// 在main.js里注册全局过滤器
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.config.globalProperties.$escapeHtml = (str) => {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
}
app.mount('#app')

然后在你的高亮组件里直接使用这个过滤器:

<template>
  <pre v-highlightjs>
    <code v-html="$escapeHtml(rawSlotContent)"></code>
  </pre>
</template>

不过这个方案还是需要你先获取插槽的原始内容,本质和方案一的核心逻辑一致。

最后提醒一句:如果插槽内容来自用户输入,一定要确保转义逻辑覆盖所有特殊字符,避免XSS安全风险哦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:29:53