Vue 3 Teleport работает только для переноса вне vue?

Vue 3 имеет новую функцию Teleport, которая заменяет плагин portal-vue в vue 2. Однако я обнаружил, что невозможно перенести компонент в место, которое контролируется 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/[email protected]/dist/vue.global.js"></script>

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

Как видите, консоль даже сообщает, что цель телепорта уже должна быть отрисована. Но как я могу сказать vue, какой компонент нужно отрендерить первым? В моем примере цель находится в доме до телепорта.

Это не было проблемой в Portal-vue, и это довольно неприятно, потому что из-за этого концепция в целом становится менее удобной.


person Fuzzyma    schedule 29.08.2020    source источник
comment
если вы добавите disabled опору <Teleport to="#dest" disabled >, он показывает содержимое телепорта, в этом случае он ведет себя как слот и по-прежнему вызывает предупреждение   -  person Boussadjra Brahim    schedule 30.08.2020
comment
Я думаю, это потому, что он по-прежнему оценивает, достижима ли цель (в конце концов, dev-версия должна помочь вам найти потенциальные ошибки)   -  person Fuzzyma    schedule 30.08.2020
comment
Интересно, что ваш пример работает без ошибок / предупреждений в приложении Vite (также с использованием [email protected]).   -  person tony19    schedule 30.08.2020
comment
Что произойдет, если вы переместите цель за компонент?   -  person Fuzzyma    schedule 30.08.2020
comment
Поместите div с идентификатором dest за <comp>   -  person Fuzzyma    schedule 30.08.2020
comment
Хорошо, просто хотел убедиться, что это тоже работает. Я не знаю вите, поэтому не знаю, почему это работает ...   -  person Fuzzyma    schedule 30.08.2020


Ответы (2)


Сообщение об ошибке Vue указывает на проблему. Там написано Invalid Teleport target on mount: null

Проблема в том, что цель не существует ЕЩЕ.

Это можно легко исправить, визуализируя только часть телепорта только после того, как компонент установлен.

Кажется, что 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" v-if="isMounted">
      Hello From Portal
    </Teleport>
  </div>`,
  data: function(){
    return { 
        isMounted: false
    }
  },
  mounted(){
    this.isMounted = true
  }
}).mount('#app')
<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>

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

person Daniel    schedule 31.08.2020
comment
Но разве это не перестает работать, когда насыпь родителя телепорта происходит раньше, чем лошадь цели? - person Fuzzyma; 31.08.2020
comment
да, вы можете реализовать на обоих или даже просмотреть всю страницу для элемента. Я подозреваю, что это своего рода функция аварийного выхода, дающая вам возможность монтировать на другом элементе, но без накладных расходов, которые может внести пользовательский плагин. - person Daniel; 31.08.2020

В этом выпуске на 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>
person Yuki Kharlamova    schedule 07.02.2021