介绍两个神奇的vue官方内置组件Teleport和Suspense

1,052 阅读5分钟

前言:

先直入主题,这文章要介绍的两个内置组件分别是TeleportSuspense。 之前vue3刚出来就知道增加了Teleport这个内置组件,作用大概是类似传送门,把某个DOM传送到别个一个DOM结构中展示,但最近做某个需求首次使用才觉得Teleport真香啊,太方便了; 而Suspense 组件侧是用于处理异步组件加载时的用户体验的组件。下面分别细说它们的作用、用法和注意事项。

一、Suspense 组件

作用简述

Suspense用于处理异步组件加载时的用户体验。它可以在组件加载完成前展示一个你自定义的效果,并在组件加载完成后隐藏它。这对于优化用户视觉体验,特别是在组件需要从服务器异步加载时是相当有用。

Suspense 基本用法

Suspense 组件能接受两个插槽分别是#default#fallback#default 插槽主要用于放置需要加载的组件,而 #fallback 插槽侧用于在组件加载期间想要显示的内容。

代码示例

<template>
  <Suspense>
    <template #default>
      <MyComponent />
    </template>
    <template #fallback>
      <div>加载中你想要显示的内容...</div>
    </template>
  </Suspense>
</template>

<script setup>
  import { defineAsyncComponent } from 'vue';

  const MyComponent = defineAsyncComponent(() => import('./MyComponent.vue')),
</script>

上述例子中,当 MyComponent 正在加载时,用户会看到#fallback中你想要展示的内容。一旦组件加载完成,Suspense 将自动切换到 MyComponent中。

Suspense 进阶用法

(1)自定义超时时间: 可以通过 timeout 属性来设置 Suspense 在显示内容之前的等待时间。这样能防止在组件快速加载时显示时间过于短暂出现闪一下的效果。

   <Suspense timeout="500">
     逻辑内容
   </Suspense>

(2) 多个异步组件优先级: 当页面中有多个异步组件时,Suspense 可以按需加载组件,先加载的组件会先显示,而内容会在所有组件加载完成前一直显示。

<template>
  <Suspense>
    <template #default>
      <MyComponentA />
      <MyComponentB />
    </template>
    <template #fallback> 加载中的内容 </template>
  </Suspense>
</template>

<script setup>
  import { defineAsyncComponent } from 'vue';

  const MyComponentA = defineAsyncComponent(() => import('./MyComponentA.vue'))
  const MyComponentB = defineAsyncComponent(() => import('./MyComponentB.vue'))
</script>


(3) 动态组件结合 Suspense Suspense能和 Vue 的动态组件 <component :is="isComponent"> 一起使用,方便处理动态加载的组件。

<template>
  <Suspense>
    <template #default>
      <component :is="isComponent" />
    </template>
    <template #fallback>
     加载中显示的内容
    </template>
  </Suspense>
</template>

(4) Suspense 结合 SSR 在服务端渲染(SSR)环境中,Suspense 会等待所有异步组件加载完成后再渲染页面,这可以确保客户端和服务器端的渲染结果一致。

(5) Suspense 的错误处理: 如果异步组件加载失败,Suspense 并不会自动处理错误。它需要我们在组件的 onErrorCaptured钩子中处理错误,或者使用全局的错误处理机制。

<script setup>
  import { defineAsyncComponent,onErrorCaptured } from 'vue';

  const MyComponent = defineAsyncComponent(() => import('./MyComponent.vue')),

  const error = ref(null);
  onErrorCaptured((err) => {
    error.value = err;
    return false; // 阻止错误冒泡
  });
</script>

二、Teleport 组件

作用简述

Teleport 组件我们将组件的渲染结果“传送”到 DOM 树中的另一个位置,而不会影响到组件自身的层级关系。这在处理模态对话框、固定定位元素、或者任何需要脱离当前组件层级结构的元素时非常有用。

Suspense 基本用法

Teleport 组件接受一个 to 属性,该属性指定目标元素的选择器。Teleport 的子元素将会被插入到由 to 目标属性指定的元素中展现出来。

代码示例

<template>
  <Teleport to="#my-root">
    <div id="my-modal" class="modal">
      <!-- 想要展示的内容 -->
    </div>
  </Teleport>
</template>

上述示例中,#my-modal 元素将被传送到具有 id="my-root" 的元素中,无论该元素在组件树中的哪个位置。

Suspense 进阶用法

(1)动态 to 属性: to 属性可以是动态的,也就是说可以根据组件的状态或用户的交互来改变传送的目标。

   <Teleport :to="targetElement">
     <!--  想要展示的内容 -->
   </Teleport>

(2)禁用 Teleport: 可以使用 disabled 属性来临时禁用 Teleport 的功能,这在某些条件下不希望进行传送时很有用。

   <Teleport to="#my-root" :disabled="!showModal">
     <!--  想要展示的内容 -->
   </Teleport>

(3)多个 Teleport 实例: 可以在同一个组件中使用多个 Teleport 实例,将不同的部分传送到不同的目标位置。

(4)事件冒泡: 使用 Teleport 时要注意事件冒泡的问题。由于元素被传送到不同的位置,事件可能会冒泡到目标元素而非原始的组件树。在处理点击或其他事件时,你可能需要考虑这一点。

(5)条件渲染: 你可以根据条件渲染 Teleport 组件,例如只在需要显示模态框时才传送元素。

   <Teleport v-if="showModal" to="#my-root">
     <!--  想要展示的内容 -->
   </Teleport>

Teleport 的注意事项

  • Teleport 不能用于根组件,因为根组件必须始终渲染到 #app 或指定的挂载点。
  • 当 Teleport 的目标元素不存在时,子元素将不会被渲染。
  • Teleport 的子元素不会影响其周围的兄弟元素,因此可以用于创建浮动或覆盖元素,而不干扰页面的布局流。

小结:

TeleportSuspenseVue3 中两个重要的内置组件,分别用于处理组件渲染位置和异步组件加载时的用户体验。 Teleport 使得组件可以灵活地渲染到文档的任意位置,而 Suspense 则确保了异步组件加载过程中的平滑过渡。 正确使用这两个组件可以显著提升应用的性能和用户体验,特别是在处理复杂的UI场景时。如果那里写的不对或者有什么建议欢迎大佬们指点一二