Vue 3 Teleport仅支持挂载到应用外部?技术问题咨询
解决Vue 3 Teleport无法挂载到应用内部元素的问题
这个问题我之前也碰到过,核心原因是Vue的模板渲染是异步的——虽然你在模板里把#dest写在了<comp>前面,但当<comp>组件初始化并尝试挂载Teleport时,#dest可能还没被Vue实际渲染到DOM中,所以会触发“teleport目标需已渲染”的错误。
下面给你几个可行的解决方案:
方案1:用v-if确保目标元素渲染后再加载Teleport组件
通过控制组件的渲染时机,让#dest完全渲染到DOM后再初始化包含Teleport的组件:
<script src="https://unpkg.com/vue@3.0.0-rc.9/dist/vue.global.js"></script> <div id="app"></div> <script> const app = { template: ` <div> <h1>App</h1> <div id="dest"></div> <comp v-if="isDestReady" /> </div>`, data() { return { isDestReady: false } }, mounted() { // 挂载后确认目标元素已存在,再渲染组件 this.isDestReady = true } } Vue.createApp(app).component('comp', { template: ` <div> A component <Teleport to="#dest"> Hello From Portal </Teleport> </div>` }).mount('#app') </script>
方案2:在Teleport组件内部监听目标元素的存在
可以在comp组件里用nextTick等待DOM更新后,再确认目标元素是否存在:
<script src="https://unpkg.com/vue@3.0.0-rc.9/dist/vue.global.js"></script> <div id="app"></div> <script> const app = { template: ` <div> <h1>App</h1> <div id="dest"></div> <comp /> </div>` } Vue.createApp(app).component('comp', { template: ` <div> A component <Teleport v-if="targetExists" to="#dest"> Hello From Portal </Teleport> </div>`, data() { return { targetExists: false } }, mounted() { this.$nextTick(() => { // 等待DOM更新后检查目标元素是否存在 this.targetExists = !!document.getElementById('dest') }) } }).mount('#app') </script>
补充:为什么portal-vue没有这个问题?
portal-vue内部做了额外的监听逻辑,会主动等待目标元素出现在DOM中后再执行挂载操作;而Vue 3原生的Teleport要求目标元素在Teleport初始化时必须已经存在于DOM中,所以两者会有这个差异。
内容的提问来源于stack exchange,提问作者Fuzzyma
相关产品推荐
相关产品推荐

