揭开 Vue Suspense 的神秘面纱

科技   2024-11-05 08:40   北京  

点击上方 程序员成长指北,关注公众号

回复1,加入高级Node交流群


你知道<Suspense>组件吗?你知道<Suspense>如何管理 Vue app 的异步依赖吗?你知道<Suspense>如何改进加载状态吗?

不知道?那就一起来学习一下吧。

<Suspense>组件是 Vue 中的一个实验性功能,旨在帮助管理组件树中的异步依赖项。

虽然它目前处于实验阶段,但这是一种在处理异步组件,特别是处理加载状态的一个新的强大方法。

Suspense 解决了什么问题?

我们知道,但凡我们处理依赖于异步数据的组件时,通常需要手动管理加载状态。一听到手动二字,就能脑补一系列麻烦了。

举个例子,假设你有一个仪表板组件,组件包含多个嵌套组件,而这些嵌套组件每个又都依赖于异步获取的数据。

如果不使用<Suspense>,那么因为这些组件中的每一个都需要自己的加载逻辑,所以很可能会导致陆续弹出不同的加载提示框,哎呀妈呀,这是多么糟糕的用户体验呀!

而使用<Suspense>,管理加载状态变得易如反掌。因为组件不需要各自处理自己的加载状态,<Suspense>允许你在等待解析组件树中的所有异步依赖项时,显示单个加载状态。

<Suspense>如何工作?

<Suspense>
  <!-- Component with async dependencies -->
  <UserProfile />

  <!-- Loading state via #fallback slot -->
  <template #fallback>
    <div class="spinner">Loading user profile...</div>
  </template>

</Suspense>

<Suspense>组件通过包装其他组件来工作。它有两个插槽:#default#fallback

  • #default插槽包含一切准备就绪后就应该显示的组件和内容。
  • #fallback插槽是定义在等待异步操作完成时应显示的内容的位置。

在渲染组件时,Vue 会尝试渲染#default插槽中的内容。一旦遇到异步依赖项(例如使用async setup()的组件),就会切换到#fallback插槽,直到一切准备就绪。

关于异步依赖项<Suspense>可以等待两种类型的异步依赖项:

  • async setup()钩子的组件:如果组件的setup函数是异步的,就自动成为<Suspense>的异步依赖项。
<script setup>
const data = await fetchData();
</script>

<template>
  <div>{{ data }}</
div>
</template>
  • 异步组件:显式定义为异步的组件。如果这些异步组件是<Suspense>组件树的一部分,那么由<Suspense>管理它们的加载状态。
<script>
export default {
  async setup() {
    const data = await fetchData();
    return { data };
  }
}
</script>

<template>
  <div>{{ data }}</
div>
</template>

处理<Suspense>事件

<Suspense>组件发出三个关键事件:pendingresolvefallback

  • pending:组件进入 pending 状态时触发,表示异步依赖正在解析中。
<Suspense @pending="handlePending">
  <template #default>
    <UserProfile />
  </template>

  <template #fallback>
    <div class="spinner">Loading...</div>
  </template>

</Suspense>

<script setup>
function handlePending() {
  console.log('Loading state started');
}
</
script>
  • resolve:一旦#default插槽中的内容完成加载并准备好显示就会发出。
<Suspense @resolve="handleResolve">
  <template #default>
    <UserProfile />
  </template>

  <template #fallback>
    <div class="spinner">Loading...</div>
  </template>

</Suspense>

<script setup>
function handleResolve() {
  console.log('Content fully loaded');
}
</
script>
  • fallback:在显示#fallback插槽内容时触发,通常是在等待异步操作完成时触发。
<Suspense @fallback="handleFallback">
  <template #default>
    <UserProfile />
  </template>

  <template #fallback>
    <div class="spinner">Loading...</div>
  </template>

</Suspense>

<script setup>
function handleFallback() {
  console.log('Showing fallback content');
}
</
script>

管理加载状态

<Suspense>的美妙之处在于管理加载状态。当组件最初被渲染时,Vue 会尝试渲染默认内容。

这时如果遇到异步操作,就会显示回退内容。只有在解析完所有异步依赖项后,才会显示默认内容。

<Suspense>
  <!-- Dashboard with async data -->
  <UserDashboard />

  <!-- Custom loading state -->
  <template #fallback>
    <div class="loading">Loading dashboard, please wait...</div>
  </template>

</Suspense>

你有没有发现,管理复杂的加载场景变得容易了呢?是的,因为整个组件树中再也不用分散多个加载指示器。

处理错误

虽然 <Suspense>非常适合管理加载状态,但它并不能直接处理错误。所以对于错误处理,我们得另想法子:Vue 的errorCaptured选项,或者父组件中的onErrorCaptured()钩子皆可。

与其他 Vue 组件组合应用

如果你想要<Suspense>与诸如<Transition><KeepAlive><RouterView>这些组件一起用,那么记得嵌套顺序很重要。

<RouterView v-slot="{ Component }">
  <template v-if="Component">
    <Transition mode="out-in">
      <KeepAlive>
        <Suspense>
          <!-- Main settings content -->
          <component :is="Component" />

          <!-- Loading spinner -->
          <template #fallback>
            <div class="loading">Loading settings...</div>
          </template>
        </Suspense>
      </KeepAlive>
    </Transition>
  </template>

</RouterView>

只有像上面这样有序地设置,我们才能顺利组合过渡、缓存和异步处理。

嵌套的<Suspense>

如果遇到更复杂的应用程序,那么我们还可能遇到嵌套的异步组件。别怕,我们有嵌套的<Suspense>组件,可以独立控制深度嵌套组件的加载状态。

<Suspense>
  <AsyncUserProfile>
    <Suspense suspensible>
      <AsyncUserDetails />
    </Suspense>
  </AsyncUserProfile>

</Suspense>

设置suspensible prop 确保了内部的<Suspense>的集成,从而允许我们对加载状态进行更精确的控制。赞。

最后的话

看到这儿,大家对<Suspense>是不是有了更深刻的理解了呢?学习不是一朝一夕的事,不积硅步无以至千里。

学习快乐,编码快乐!

原文链接:

https://www.trevorlasn.com/blog/understanding-vue-suspense

END

Node 社群


我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。

   “分享、点赞在看” 支持一波👍

程序员成长指北
专注 Node.js 技术栈分享,从 前端 到 Node.js 再到 后端数据库,祝您成为优秀的高级 Node.js 全栈工程师。一个有趣的且乐于分享的人。座右铭:今天未完成的,明天更不会完成。
 最新文章