Vue3结合vue3-sfc-loader动态添加.vue组件失败的解决求助
动态加载Vue3组件问题(使用vue3-sfc-loader)
我正在使用vue3-sfc-loader注册并加载.vue组件,以下两种场景均能正常运行:
示例1:全局注册后直接在模板使用
<div id="app"> <ae-studio></ae-studio> </div> <script> const app = Vue.createApp({}); app.component('ae-studio', loadVM("/components/aeStudio.vue")); const vueInstance = app.mount("#app"); </script>
示例2:在组件内注册子组件
<template> <div> append studio header </div> <table style="width:100%;"> <tr> <td style="width:50%"> <ae-nav></ae-nav> </td> <td style="width:50%"> <ae-docsview></ae-docsview> </td> </tr> </table> </template> <script> app.component('ae-nav', loadVM("/components/aeNav.vue")); app.component('ae-docsview', loadVM("/components/aeDocsview.vue")); </script>
但当我尝试通过点击按钮动态添加组件时,如下代码无法正常工作:
<template> <button @click="show('this is a message')">Click to add Component here</button> <div id="comPlace">A place for new component</div> </template> <script> app.component('ae-test', loadVM("/components/aeTest.vue")); export default { setup(props) { return { show: (msg) => { console.log(msg); let cPlace = document.getElementById("comPlace"); cPlace.innerHTML='<ae-test>qqqqqqqqqqqqqqqqqqq</ae-test>'; let a = app.component('ae-test', loadVM("/components/aeTest.vue")); } }; } } </script>
我尝试使用forceUpdate方法,但问题仍未解决。请问该如何解决此问题?我已创建GitHub仓库用于追踪问题。
解决方案
直接通过innerHTML插入组件标签的方式无效,因为Vue只会编译初始渲染的模板内容,后续手动插入的DOM不会被Vue解析处理。需要使用Vue官方提供的动态组件方式,或者手动挂载组件:
方法一:使用动态组件(推荐)
利用Vue的<component>标签,通过响应式变量控制组件的显示:
<template> <button @click="show('this is a message')">Click to add Component here</button> <div> <!-- 动态组件,v-if控制是否显示 --> <component :is="activeComponent" v-if="activeComponent"> qqqqqqqqqqqqqqqqqqq </component> </div> </template> <script> import { ref } from 'vue'; // 提前加载组件(也可以在show方法内异步加载) const AeTest = loadVM("/components/aeTest.vue"); export default { setup(props) { const activeComponent = ref(null); const show = (msg) => { console.log(msg); // 切换为目标组件 activeComponent.value = AeTest; }; return { show, activeComponent }; } } </script>
方法二:手动挂载组件到指定DOM
如果需要手动操作DOM容器,可以通过Vue的API创建组件实例并挂载:
<template> <button @click="show('this is a message')">Click to add Component here</button> <!-- 使用ref获取DOM容器 --> <div ref="comPlace">A place for new component</div> </template> <script> import { ref } from 'vue'; export default { setup(props) { const comPlace = ref(null); const show = async (msg) => { console.log(msg); // 异步加载组件 const AeTest = await loadVM("/components/aeTest.vue"); // 清空容器内容 comPlace.value.innerHTML = ''; // 创建组件实例并挂载到容器 const componentApp = Vue.createApp(AeTest); componentApp.mount(comPlace.value); }; return { show, comPlace }; } } </script>
原因说明
Vue的模板编译是在初始化阶段完成的,直接修改innerHTML插入的组件标签不属于Vue的响应式系统管理范围,因此不会触发组件的实例化和渲染。必须通过Vue提供的API来动态管理组件,才能让Vue正确处理组件的生命周期和渲染逻辑。
内容的提问来源于stack exchange,提问作者Mohsen Mirshahreza
相关产品推荐
相关产品推荐

