导读:本期聚焦于小伙伴创作的《Vue中如何将带有特定标记的字符串渲染为动态组件如router-link》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Vue中如何将带有特定标记的字符串渲染为动态组件如router-link》有用,将其分享出去将是对创作者最好的鼓励。

在Vue项目开发中,我们经常会遇到后端返回包含特定标记的字符串的场景,比如字符串里带有router-link标记,需要把这段字符串渲染成可点击的路由链接。直接用v-html渲染会有XSS风险,也不符合Vue的组件化开发理念,这时候就需要通过解析字符串、匹配动态组件的方式实现需求。

Vue中如何将带有特定标记的字符串渲染为动态组件如router-link

核心实现思路

整个实现过程可以分为三个核心步骤:

  • 解析带有特定标记的字符串,拆分出普通文本和标记包裹的内容
  • 建立标记和对应Vue组件的映射关系,比如把router-link标记映射到RouterLink组件
  • 使用Vue的动态组件component或者渲染函数,把解析后的内容渲染到页面上

准备工作

首先需要在项目中引入需要的组件,比如路由的RouterLink组件,同时定义好标记和组件的映射表:

import { RouterLink } from 'vue-router'
import { h } from 'vue'

// 定义标记和组件的映射关系,key是标记名称,value是对应的组件
const componentMap = {
  'router-link': RouterLink
}

// 示例待解析的字符串,标记用方括号包裹,格式为 [标记名 属性键值对]内容[/标记名]
const rawString = '点击[router-link to="/home"]首页[/router-link]跳转,或者[router-link to="/about"]关于我们[/router-link]查看详情'

字符串解析函数实现

我们需要写一个解析函数,把原始字符串拆分成普通文本和标记组件两部分,这里用正则表达式匹配标记结构:

/**
 * 解析带有特定标记的字符串
 * @param {string} str 原始字符串
 * @returns {Array} 解析后的节点数组,每个节点是文本或者组件配置
 */
function parseStringWithTags(str) {
  // 匹配标记的正则,格式为 [标记名 属性]内容[/标记名]
  const tagReg = /\[(\w+(?:-\w+)*)(?:\s+([^\]]*))?\](.*?)\[\/\1\]/g
  const nodes = []
  let lastIndex = 0
  let match

  while ((match = tagReg.exec(str)) !== null) {
    // 添加标记前面的普通文本
    if (match.index > lastIndex) {
      nodes.push({
        type: 'text',
        content: str.slice(lastIndex, match.index)
      })
    }

    const tagName = match[1]
    const attrStr = match[2] || ''
    const content = match[3]

    // 解析标记的属性,比如 to="/home" 这种键值对
    const attrs = {}
    if (attrStr) {
      const attrReg = /(\w+)="([^"]*)"/g
      let attrMatch
      while ((attrMatch = attrReg.exec(attrStr)) !== null) {
        attrs[attrMatch[1]] = attrMatch[2]
      }
    }

    // 添加组件节点
    nodes.push({
      type: 'component',
      tag: tagName,
      attrs,
      content
    })

    lastIndex = match.index + match[0].length
  }

  // 添加最后剩余的普通文本
  if (lastIndex < str.length) {
    nodes.push({
      type: 'text',
      content: str.slice(lastIndex)
    })
  }

  return nodes
}

渲染组件实现

解析完成后,我们可以写一个渲染组件,把解析后的节点渲染成实际的页面内容:

<template>
  <div class="dynamic-string-renderer">
    <template v-for="(node, index) in parsedNodes" :key="index">
      <!-- 普通文本直接渲染 -->
      <span v-if="node.type === 'text'">{{ node.content }}</span>
      <!-- 组件节点用动态组件渲染 -->
      <component
        v-else
        :is="componentMap[node.tag]"
        v-bind="node.attrs"
      >
        {{ node.content }}
      </component>
    </template>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { RouterLink } from 'vue-router'

// 组件映射表
const componentMap = {
  'router-link': RouterLink
}

// 接收父组件传入的原始字符串
const props = defineProps({
  rawString: {
    type: String,
    required: true
  }
})

// 解析字符串得到节点数组
const parsedNodes = computed(() => {
  const str = props.rawString
  const tagReg = /\[(\w+(?:-\w+)*)(?:\s+([^\]]*))?\](.*?)\[\/\1\]/g
  const nodes = []
  let lastIndex = 0
  let match

  while ((match = tagReg.exec(str)) !== null) {
    if (match.index > lastIndex) {
      nodes.push({
        type: 'text',
        content: str.slice(lastIndex, match.index)
      })
    }

    const tagName = match[1]
    const attrStr = match[2] || ''
    const content = match[3]

    const attrs = {}
    if (attrStr) {
      const attrReg = /(\w+)="([^"]*)"/g
      let attrMatch
      while ((attrMatch = attrReg.exec(attrStr)) !== null) {
        attrs[attrMatch[1]] = attrMatch[2]
      }
    }

    nodes.push({
      type: 'component',
      tag: tagName,
      attrs,
      content
    })

    lastIndex = match.index + match[0].length
  }

  if (lastIndex < str.length) {
    nodes.push({
      type: 'text',
      content: str.slice(lastIndex)
    })
  }

  return nodes
})
</script>

使用示例

在页面中使用这个渲染组件,传入带有router-link标记的字符串即可:

<template>
  <div>
    <h3>动态渲染字符串中的组件</h3>
    <DynamicStringRenderer
      raw-string="欢迎访问,点击[router-link to="/home"]首页[/router-link]返回主页,或者[router-link to="/user"]个人中心[/router-link]查看信息"
    />
  </div>
</template>

<script setup>
import DynamicStringRenderer from './components/DynamicStringRenderer.vue'
</script>

注意事项

  • 标记格式可以根据项目需求调整,正则匹配规则也要同步修改,比如如果标记用花括号包裹,就调整对应的正则
  • 如果需要支持嵌套标记,比如router-link里面包含其他组件标记,需要递归解析节点,上面的示例是基础版本,支持扩展
  • 属性解析目前只支持键值对带双引号的形式,如果有其他属性格式,可以补充对应的正则匹配规则
  • 如果不需要路由的router-link,也可以把映射表里的组件换成自定义组件,实现任意动态组件的渲染

扩展:支持嵌套标记

如果需要支持标记嵌套,只需要把解析函数改成递归解析即可,比如解析[router-link to="/home"]点击[span class="red"]这里[/span]跳转[/router-link]这种结构:

function parseNode(str, start = 0, end = str.length) {
  const nodes = []
  let lastIndex = start
  const tagReg = /\[(\w+(?:-\w+)*)(?:\s+([^\]]*))?\](.*?)\[\/\1\]/g
  let match

  // 重置正则的lastIndex,避免匹配错误
  tagReg.lastIndex = start

  while ((match = tagReg.exec(str)) !== null && match.index < end) {
    if (match.index > lastIndex) {
      nodes.push({
        type: 'text',
        content: str.slice(lastIndex, match.index)
      })
    }

    const tagName = match[1]
    const attrStr = match[2] || ''
    const contentStart = match.index + match[1].length + (attrStr ? attrStr.length + 2 : 0) + 2 // 跳过[tagname attr]
    const contentEnd = match.index + match[0].length - tagName.length - 3 // 跳过[/tagname]

    // 递归解析子内容
    const children = parseNode(str, contentStart, contentEnd)

    const attrs = {}
    if (attrStr) {
      const attrReg = /(\w+)="([^"]*)"/g
      let attrMatch
      while ((attrMatch = attrReg.exec(attrStr)) !== null) {
        attrs[attrMatch[1]] = attrMatch[2]
      }
    }

    nodes.push({
      type: 'component',
      tag: tagName,
      attrs,
      children
    })

    lastIndex = match.index + match[0].length
  }

  if (lastIndex < end) {
    nodes.push({
      type: 'text',
      content: str.slice(lastIndex, end)
    })
  }

  return nodes
}

对应的渲染组件也需要调整,支持渲染子节点,这样就可以实现任意层级的标记嵌套渲染了。

Vue动态组件字符串解析router-link渲染修改时间:2026-06-02 05:10:01

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。