官方文档:Teleport

该组件可以将插槽接收的内容渲染到指定的dom位置,常见的一个业务需求就是model弹窗了,我们有时候会在子组件里面去书写一个弹窗,但是这个弹窗是全局性的,为了防止被定位元素影响,我们vue2时会在mounted生命钩子里手动将model的dom传入body里面,而且还得在销毁时从body移除。

vue3提供了teleport组件,它和react的传送门组件其实效果相同,它有两个props属性:

to

to支持字符串和html元素,如果是字符串,指的是css选择器,而html元素则是dom。

disabled

接收一个布尔值,表示是否禁用传送门,通过这个属性我们可以很方便的实现一个video视频的小屏处理,当用户往下滚动时,可以将video传送到右下角小屏展示。

interface TeleportProps {
  /**
   * 必填项。指定目标容器。
   * 可以是选择器或实际元素。
   */
  to: string | HTMLElement
  /**
   * 当值为 `true` 时,内容将保留在其原始位置
   * 而不是移动到目标容器中。
   * 可以动态更改。
   */
  disabled?: boolean
}
<button @click="open = true">Open Modal</button>

<Teleport to="body" :disabled="disabled">
  <div v-if="open" class="modal">
    <p>Hello from the modal!</p>
    <button @click="open = false">Close</button>
  </div>
</Teleport>

官方表示该组件只是改变了渲染dom结构,所以它不会影响组件之间的逻辑关系,也就说,除了我们在代码编写层逻辑关系不变,它的虚拟dom位置也不会发生改变。

所以Teleport里的组件通过$parent获取到的,其实并不是Teleport本身,Teleport可以视为一个假组件,所以我们依旧可以拿到“逻辑”上的父级组件。

如果存在多个Teleport的to属性指向同一个html元素,那么会根据渲染的先后顺序插入(顺次追加)。

高阶使用

动态绑定to

事实上to这个属性是可以动态绑定的,当我们的to属性发生改变时,teleport会先将内容移动到新的位置。

<Teleport :to="container">

</Teleport>

ref获取内容

ref是可以正常获取到Teleport内的内容的

<template>
  <div>
    <button @click="onClick">s</button>

    <Teleport to="body">
      <h2 v-if="flag" ref="title">标题</h2>
    </Teleport>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, nextTick } from "vue";

export default defineComponent({
  setup() {
    const flag = ref(false);
    const title = ref();

    function onClick() {
      flag.value = !flag.value;
      nextTick(() => {
        console.log(title);
      });
    }

    return {
      flag,
      title,
      onClick,
    };
  },
});
</script>
分类: vue3 快速上手 标签: vue3Teleport传送门

评论

暂无评论数据

暂无评论数据

目录