Телепорт в компоненте из слота Vue3

Я хочу создать компонент вкладок для моей библиотеки компонентов. я хочу tabs и компоненты для работы следующим образом:

      <b-tabs>
  <b-tab
    :title="'tab 1'"
    :is-active="false"
  >
    tab content1
  </b-tab>
  <b-tab
    :title="'tab 2'"
    :is-active="false"
  >
    tab content2
  </b-tab>
  <b-tab
    :title="'tab 3'"
    :is-active="true"
  >
    tab content3
  </b-tab>
</b-tabs>

Итак, у нас есть два компонента, и у них есть некоторые реквизиты, включая is-active, который по умолчанию будет ложным.

Родительский компонент - tabs.vue будет что-то вроде этого

      <template>
  <section :class="mode ? 'tabs--light' : 'tabs--dark'" @change-tab="selectTab(2)">
    <div :id="`tabs-top-tabId`" class="tabs__menu"></div>
    <slot></slot>
  </section>
</template>

здесь у нас есть обертка для нашего сингла tabкоторый будет отображаться здесь с помощью слота. Здесь, в этом «родительском» компоненте, мы также держим selectedIndex которые определяют, какая вкладка выбрана, и функция для изменения этого значения.

        setup () {
    const tabId = Math.random() // TODO: use uuid;
    const data = reactive<{selectedIndex: number}>({
      selectedIndex: 0
    })

    const selectTab = (i: number) => {
      data.selectedIndex = i
    }

    return {
      tabId,
      ...toRefs(data),
      selectTab
    }
  }

TL; DR Теперь, как вы, ребята, уже могли заметить, у меня есть div с классом tabs__menuв который я хочу телепортировать что-то. Как title реквизит входит в <tab> компонент, который отображается слотом в tabs.vue, я хочу телепортироваться с вкладки на вкладки.

Мой tab.vue:

      <template>
  <h1>tab.vue {{ title }}</h1>
  <div class="tab" v-bind="$attrs">
    <teleport :to="`#tabs-top-tabId`" @click="$emit('changeTab')">
      <span style="color: red">{{ title }}</span>
    </teleport>
    <keep-alive>
      <slot v-if="isActive"></slot>
    </keep-alive>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'

export default defineComponent({
  props: {
    title: {
      type: String as PropType<string>,
      required: true
    },
    isActive: {
      type: Boolean as PropType<boolean>,
      required: true
    }
    // tabId: {
    //   type: Number as PropType<number>, // TODO: change to string after changing it to uuid;
    //   required: true
    // }
  }
})
</script>

Однако это spanне телепортируется. Когда я запускаю первый фрагмент этого сообщения, я не вижу его отображаемого и не вижу в DOM.

Почему телепортированный интервал не отображается?

1 ответ

Недавно я столкнулся с этой проблемой при использовании element-plus с утилитами vue test и Jest. Не уверен, что это поможет, но вот мой обходной путь.

      const wrapper = mount(YourComponent, {
  global: {
    stubs: {
      teleport: { template: '<div />' },
    },
  },
})
Другие вопросы по тегам