Vue 3如何将字符串内的{{}}插值解析为自定义Vue组件而非纯HTML
你正则替换后不生效的核心原因是:Vue不会把普通字符串里的自定义组件标签解析为真实组件,不管是直接插值还是用v-html渲染,都只会把内容当成纯文本/普通HTML处理,因此要实现需求,必须把原始字符串拆分为独立的节点片段,分别渲染文本和自定义组件。
实现方案
方案:拆分字符串片段动态渲染(支持Vue2/Vue3,无需v-html)
步骤1:正则拆分原始字符串
首先用正则把包含{{}}插值的字符串,拆分为「普通文本片段」和「变量插值片段」的集合:
const rawStr = `These questions will address {{ selected }}. It is influenced by the following parents: {{ parent }}.` const interpolateReg = /{{\s*([a-zA-Z0-9_]+)\s*}}/g const fragments = [] let lastPos = 0 let match while (match = interpolateReg.exec(rawStr)) { // 插入匹配位置之前的普通文本 if (match.index > lastPos) { fragments.push({ type: 'text', content: rawStr.slice(lastPos, match.index) }) } // 插入变量片段 fragments.push({ type: 'variable', varName: match[1] }) lastPos = interpolateReg.lastIndex } // 插入剩余的末尾文本 if (lastPos < rawStr.length) { fragments.push({ type: 'text', content: rawStr.slice(lastPos) }) }
拆分后得到的fragments结构示例:
[ { type: 'text', content: 'These questions will address ' }, { type: 'variable', varName: 'selected' }, { type: 'text', content: '. It is influenced by the following parents: ' }, { type: 'variable', varName: 'parent' }, { type: 'text', content: '.' } ]
步骤2:模板中动态渲染节点
遍历拆分后的片段,普通文本直接渲染为文本节点,变量片段直接渲染你的StateComponent组件即可:
<script setup> import StateComponent from './StateComponent.vue' // 上面拆分得到的fragments数组 const fragments = [/* ... */] // 存储所有变量对应的值 const stateMap = { selected: '你要传给selected的值', parent: '你要传给parent的值' } </script> <template> <div class="content-wrapper"> <template v-for="(item, index) in fragments" :key="index"> <!-- 普通文本直接渲染 --> <span v-if="item.type === 'text'">{{ item.content }}</span> <!-- 变量部分渲染自定义组件 --> <StateComponent v-else :state="stateMap[item.varName]" /> </template> </div> </template>
注意事项
- 该方案完全不涉及
v-html,所有组件都是正常的Vue组件渲染,支持所有组件的生命周期、事件绑定等能力 - 如果你的字符串内容是服务端动态返回的,只要保证插值的变量名和
stateMap里的key对应即可,无需提前固定字符串格式 - 不要使用运行时拼接组件标签字符串的方式实现,除非你引入带编译器的完整版Vue,会额外增加包体积且存在安全风险。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

