Vue中使用动态组件填充插槽未正确渲染的问题求助
你好呀!刚看到你的问题,作为Vue新手遇到这种动态组件的坑确实容易懵,我来帮你捋捋~
先确认下我理解的场景对不对:你有一个BaseIcon组件,结构是这样的:
<template> <svg> <g> <slot /> </g> </svg> </template>
你想根据item.icon的值(比如示例里的Plasmid),通过动态组件来渲染对应的IconPlasmid组件,写法是:
<IconBase> <component :is="'Icon'+ item.icon"></component> </IconBase>
结果浏览器里只渲染出了<IconPlasmid></IconPlasmid>这个空标签,没有显示组件内部的path路径;但如果直接硬编码写<IconPlasmid></IconPlasmid>,就能正常渲染出图标对应的path,对吧?
问题出在哪?
核心原因是动态组件is属性的使用方式。如果你的IconPlasmid是局部注册的组件,当你用字符串(比如"IconPlasmid")作为is的值时,Vue没办法在当前作用域里匹配到对应的组件定义,所以会把它当成一个普通的自定义HTML标签来处理,而不是去渲染组件内部的内容。
而你硬编码写<IconPlasmid>的时候,Vue的模板编译器在编译阶段就会识别到这是你已经局部注册过的组件,所以能正确解析渲染出内部的path。
给你两个解决办法
方法一:直接传入组件对象(推荐,更可靠)
你可以先把所有要用的图标组件整理到一个对象里,比如在使用的父组件中:
// 先引入需要的图标组件 import IconPlasmid from './IconPlasmid.vue' // 要是有其他图标,也一起import进来 const iconComponents = { IconPlasmid // 比如 IconUser, IconHome 之类的都可以加进来 }
然后在模板里直接引用这个对象里的组件,不用字符串拼接:
<IconBase> <component :is="iconComponents['Icon' + item.icon]"></component> </IconBase>
这样Vue能直接拿到组件的对象引用,不管是局部还是全局注册,都能正确渲染出组件内部的内容。
方法二:全局注册所有图标组件
如果你的图标组件数量不多,也可以在项目的入口文件(比如main.js)里把所有图标组件全局注册:
import { createApp } from 'vue' import App from './App.vue' import IconPlasmid from './IconPlasmid.vue' const app = createApp(App) // 注册全局组件 app.component('IconPlasmid', IconPlasmid) // 其他图标组件也按这个方式注册 app.mount('#app')
全局注册后,你原来用字符串拼接的写法就能正常工作了,因为Vue能在全局组件注册表中找到对应的组件。
小补充
如果是Vue 2的项目,局部注册的组件用字符串名称作为is的值偶尔能生效,但Vue 3对动态组件的is属性做了规范调整,更推荐直接传入组件对象,所以方法一的兼容性和稳定性会更好~
作为Vue新手,遇到这种细节问题真的很正常,慢慢来就好啦,希望这个解决方法能帮到你!
内容来源于stack exchange

