【问题标题】:Does Vue 3 Teleport only works to port outside vue?Vue 3 Teleport 是否仅适用于移植到 vue 外部?
【发布时间】:2020-12-18 11:31:17
【问题描述】:

Vue 3 有一个新的 Teleport 功能,它取代了 vue 2 中的 portal-vue 插件。但是,我发现不可能将组件移植到由 vue 控制的地方(=在 vue 应用程序中)。它仅在移植到外部(主体、其他元素...)时才有效。

const app = {
  template: `
  <div>
    <h1>App</h1>
    <div id="dest"></div>
    <comp />
  </div>`
}


Vue.createApp(app).component('comp', {
  template: `
  <div>
    A component
    <Teleport to="#dest">
      Hello From Portal
    </Teleport>
  </div>`
}).mount('#app')
<script src="https://unpkg.com/vue@3.0.0-rc.9/dist/vue.global.js"></script>

<div id="app"></div>

如您所见,控制台甚至会报告传送目标需要已经渲染。但是如何告诉 vue 先渲染哪个组件呢?在我的示例中,目标位于传送之前的 dom 中。

这在portal-vue 中不是问题,而且相当糟糕,因为它使整个概念变得不那么可用。

【问题讨论】:

  • 如果你添加 disabled prop &lt;Teleport to="#dest" disabled &gt; 它会显示传送内容,在这种情况下它表现为一个插槽,它仍然会发出警告
  • 我认为这是因为它仍然会评估目标是否可达(开发版毕竟应该可以帮助您找到潜在的错误)
  • 有趣的是,您的示例在 Vite 应用程序中没有错误/警告(也使用 vue@3.0.0-rc.9)。
  • 如果将目标移到组件后面会怎样?
  • 把id为dest的div放在&lt;comp&gt;后面

标签: vue.js vuejs3 vue-teleport


【解决方案1】:

Vue 错误消息类型指出了问题所在。它说Invalid Teleport target on mount: null

问题是目标不存在YET

这可以通过仅在组件安装后仅渲染传送部分来轻松解决。

似乎这是 Vue 应该在没有明确检查的情况下处理的事情。当您将 id 作为字符串传递时,很难判断目标是否是 Vue 组件,尤其是在尚未渲染的情况下。但我只是在这里猜测团队的意图。

const app = {
  template: `
  <div>
    <h1>App</h1>
    <div id="dest"></div>
    <comp />
  </div>`
}

Vue.createApp(app).component('comp', {
  template: `
  <div>
    A component
    <Teleport to="#dest" v-if="isMounted">
      Hello From Portal
    </Teleport>
  </div>`,
  data: function(){
    return { 
        isMounted: false
    }
  },
  mounted(){
    this.isMounted = true
  }
}).mount('#app')
<script src="https://unpkg.com/vue@3.0.0-rc.9/dist/vue.global.js"></script>

<div id="app"></div>

【讨论】:

  • 但是当传送的“父”的土堆比目标的挂载更早发生时,这不会停止工作吗?
  • 是的,您可以在两者上实现,甚至查看整个页面的元素。我怀疑这有点像逃生舱口功能,让您有机会安装在另一个元素上,但没有自定义插件可能引入的开销。
【解决方案2】:

GH 上的这个问题中包含问题解决。 应该是这样的

   //Root template in App.vue(it doesn't need to wrap in a div or smth else)
<template>
    <div class="modal" :style="style">
        <div class="modal-background"></div>
        <div class="modal-content">
            <div id="modal"></div>
        </div>
        <button class="modal-close is-large" aria-label="close" 
        @click="modal.hideModal"></button>
    </div>

    // App instance
    <section class="section">
            <div class="container">
                <Navbar/>
                <router-view/>
            </div>
        </section>
</template>

【讨论】:

    猜你喜欢
    • 2021-06-25
    • 2020-12-31
    • 2021-07-17
    • 2021-03-13
    • 1970-01-01
    • 2019-01-02
    • 2020-12-24
    • 1970-01-01
    • 2017-10-26
    相关资源
    最近更新 更多