Vue中将含哈希标签的字符串转vNode:替换a为router-link遇阻
问题描述
数据库中存储的字符串格式如下:
Lorem #ipsum dolor sit amet, #consectetur adipiscing elit, sed do #eiusmod tempor incididunt ut labore et dolore magna aliqua.
其中带#前缀的词汇为哈希标签,需求是将这些标签转为Vue Router的router-link组件,实现路由跳转。
当前已实现将标签转为普通<a>标签的代码,但替换为router-link后,标签仅被渲染为普通DOM元素,未被Vue编译,无法正常跳转:
let caption = ref(props.caption); // 对应上述文本 const tagRegex = /(#+[a-zA-Z0-9(_)]{1,})/g; caption.value = caption.value.replace(tagRegex, `<a href="/$1">$1</a>`); return () => h("span", { "innerHTML": caption.value, class: "text-pre" });
尝试过替换为router-link标签、改用v-html、手动创建子节点等方式,均未成功,求可行实现方案。
解决方案
innerHTML和v-html仅能渲染纯HTML字符串,无法触发Vue组件的编译,因此不能用这种方式渲染router-link。正确做法是将原字符串拆分为文本片段和标签组件的数组,通过Vue渲染函数直接创建组件实例。
具体实现代码
import { h, ref } from 'vue'; import { RouterLink } from 'vue-router'; export default { props: ['caption'], setup(props) { const tagRegex = /(#+[a-zA-Z0-9(_)]{1,})/g; // 按哈希标签拆分字符串,得到文本与标签交替的片段数组 const contentFragments = ref(props.caption.split(tagRegex)); return () => h('span', { class: 'text-pre' }, contentFragments.value.map(fragment => { // 判断当前片段是否为哈希标签 if (tagRegex.test(fragment)) { // 创建router-link组件,to属性设置为对应路径 return h(RouterLink, { to: `/${fragment}` }, fragment); } // 普通文本直接返回作为文本节点 return fragment; }) ); } };
核心逻辑说明
- 拆分字符串:使用
split(tagRegex)将原字符串按哈希标签拆分,得到的数组结构为[普通文本, 哈希标签, 普通文本, 哈希标签, ...] - 遍历生成节点:遍历片段数组,对每个片段判断是否为哈希标签,是则创建
router-link组件实例,否则直接返回文本内容 - 渲染组合:通过Vue的
h渲染函数,将所有片段节点组合到目标<span>中,此时router-link会被Vue正常编译,具备路由跳转功能
内容的提问来源于stack exchange,提问作者Ayeye Brazo
相关产品推荐
相关产品推荐

