搜索
首页web前端Vue.js详解Vue3 Suspense:是什么?能干什么?如何用?

本篇文章带大家深入了解一下Vue3  Suspense,聊聊Suspense是什么、能干什么,以及如何使用它,希望对大家有所帮助!

详解Vue3  Suspense:是什么?能干什么?如何用?

Suspense 不是你想的那样。是的,它帮助我们处理异步组件,但它的作用远不止于此。(学习视频分享:vue视频教程

Suspense 允许我们协调整个应用程序的加载状态,包括所有深度嵌套的组件。而不是像一个爆米花用户界面一样,到处都是 loading,组件突然奔的一下到位

有了 Suspense, 我们可以有一个单一的、有组织的系统,一次性加载所有东西。

而且,Suspense 也给我们提供了细粒度的控制,所以如果需要的话,我们可以在两者之间实现一些东西。

在这篇文章中,我们将学到很多关于 Suspense 的知识--它是什么,能干什么,以及如何使用它。

首先,我们将仔细看看这些爆米花界面。然后,在看看如何使用Suspense来解决这些问题。之后,尝试通过在整个应用程序中嵌套Suspense来获得更精细的控制。最后,简单看看如何使用占位符来丰富我们的用户界面。

爆米花UI-- Suspense 之前

事例地址:https://codesandbox.io/s/uncoordinated-loading-before-suspense-srh8ll?file=/src/App.vue

如果没有 Suspense,每个组件都必须单独处理其加载状态。

这可能导致一些相当糟糕的用户体验,多个加载按钮和内容突然出现在屏幕上,就像你在制作爆米花一样。

虽然,我们可以创建抽象组件来处理这些加载状态,但这比使用Suspense要困难得多。有一个单一的点来管理加载状态,比每个组件做自己的事情要容易维护得多。

在事例中,我们使用BeforeSuspense组件来模拟一个内部处理加载状态的组件。把它命名为BeforeSuspense,因为一旦我们实现了Suspense,我们就会把它重构为WithSuspense组件。

BeforeSuspense.vue

<template>
    <div class="async-component" :class="!loading && &#39;loaded&#39;">
      <Spinner v-if="loading" />
      <slot />
    </div>
</template>

<script setup>
import { ref } from 'vue'
import Spinner from './Spinner.vue'

const loading = ref(true)
const { time } = defineProps({
  time: {
    type: Number,
    default: 2000
  }
})

setTimeout(() => (loading.value = false), time)
</script>

一开始设置 loading 为 true,所以显示 Spinner 组件。然后,当setTimeout完成后,将 loading 设置为 false,隐藏 Spinner  并使组件的背景为绿色。

在这个组件中,还包括一个 slot ,这样其它组件就可以套在 BeforeSuspense 组件中了:

<template>
    <button @click="reload">Reload page</button>
    <BeforeSuspense time="3000">
      <BeforeSuspense time="2000" />
      <BeforeSuspense time="1000">
        <BeforeSuspense time="500" />
        <BeforeSuspense time="4000" />
      </BeforeSuspense>
    </BeforeSuspense>
</template>

没有什么太花哨的东西。只是一些嵌套的组件,有不同的时间值传递给它们。

下面,我们来看看怎么通过使用 Suspense 组件来改进这个爆米花用户界面。

Suspense

事例地址:https://codesandbox.io/s/coordinated-loading-with-suspense-b6dcbi?file=/src/App.vue

现在,我们使用Suspense来处理这些乱七八糟的东西,并将其变成一个更好的用户体验。

不过,首先我们需要快速了解一下Suspense到底是什么

Suspense 基础知识

以下是 Suspense 部分的基本结构

<Suspense>
  <!-- Async component here -->

  <template #fallback>
      <!-- Sync loading state component here -->
  </template>
</Suspense>

为了使用Suspense,把异步组件放入 default 槽,把回退加载状态放入 fallback 槽。

异步组件是以下两种情况之一:

  • 一个带有async setup函数的组件,该组件返回一个Promise,或者在script setup中使用顶级await
  • 使用 defineAsyncComponent 异步加载的组件

无论哪种方式,我们最终都会得到一个开始未解决 的 Promise ,然后最终得到解决。

当该 Promise 未被解决时,Suspense 组件将显示 fallback  槽中的内容。然后,当Promise 被解决时,它会在 default  槽中显示该异步组件。

注意: 这里没有错误处理路基。起初我以为有,但这是对悬念的一个常见误解。如果想知道是什么导致了错误。可以使用onErrorCaptured钩子来捕捉错误,但这是一个独立于Suspense的功能。

现在我们对Suspense有了一些了解,让我们回到我们的演示应用程序。

管理异步依赖关系

为了让Suspense管理我们的加载状态,首先需要将BeforeSuspense组件转换成一个异步组件

我们将它命名为 WithSuspense,内容如下:

<template>
  <div class="async-component loaded">
    <!-- 这里不需要一个 Spiner 了,因为加载是在根部处理的 -->
    <slot />
  </div>
</template>

<script setup>
const { time } = defineProps({
  time: {
    type: Number,
    required: true
  }
})
// 加入一个延迟,以模拟加载数据
await new Promise(resolve => {
  setTimeout(() => {
    resolve()
  }, time)
})
</script>

我们已经完全删除了加载状态的Spinner,因为这个组件不再有加载状态了。

因为这是一个异步组件,setup 函数直到它完成加载才会返回。该组件只有在 setup 函数完成后才会被加载。因此,与BeforeSuspense组件不同,WithSuspense组件内容在加载完毕之前不会被渲染。

这对任何异步组件来说都是如此,不管它是如何被使用的。在setup函数返回(如果是同步的)或解析(如果是异步的)之前,它不会渲染任何东西。

有了WithSuspense组件,我们仍然需要重构我们的App组件,以便在Suspense组件中使用这个组件。

<template>
  <button @click="reload">Reload page</button>
  <Suspense>
    <WithSuspense :time="2000">
      <WithSuspense :time="1500" />
      <WithSuspense :time="1200">
        <WithSuspense :time="1000" />
        <WithSuspense :time="5000" />
      </WithSuspense>
    </WithSuspense>

    <template #fallback>
      <Spinner />
    </template>
  </Suspense>
</template>

结构和之前一样,但这次是在 Suspense 组件的默认槽中。我们还加入了 fallback  槽,在加载时渲染我们的Spinner组件。

在演示中,你会看到它显示加载按钮,直到所有的组件都加载完毕。只有在那时,它才会显示现在完全加载的组件树。

异步瀑布

如果你仔细注意,你会注意到这些组件并不像你想象的那样是并联加载的。

总的加载时间不是基于最慢的组件(5秒)。相反,这个时间要长得多。这是因为Vue只有在父异步组件完全解析后才会开始加载子组件。

你可以通过把日志放到WithSuspense组件中来测试这一点。一个在安装开始跟踪安装,一个在我们调用解决之前。

最初使用BeforeSuspense组件的例子中,整个组件树被挂载,无需等待,所有的 "异步 "操作都是并行启动的。这意味着Suspense有可能通过引入这种异步瀑布而影响性能。所以请记住这一点。

嵌套 Suspense  以隔离子树

事例地址:https://codesandbox.io/s/nesting-suspense-wt0q7k?file=/src/App.vue

这里有一个深度嵌套的组件,它需要整整5秒来加载,阻塞了整个UI,尽管大多数组件加载完成的时间要早得多。

但对我们来说有一个解决方案

通过进一步嵌套第二个Suspense组件,我们可以在等待这个组件完成加载时显示应用程序的其他部分。

<template>
  <button @click="reload">Reload page</button>
  <Suspense>
    <WithSuspense :time="2000">
      <WithSuspense :time="1500" />
      <WithSuspense :time="1200">
        <WithSuspense :time="1000" />

                <!-- Nest a second Suspense component -->
        <Suspense>
          <WithSuspense :time="5000" />
          <template #fallback>
            <Spinner />
          </template>
        </Suspense>
      </WithSuspense>
    </WithSuspense>

    <template #fallback>
      <Spinner />
    </template>
  </Suspense>
</template>

将其包裹在第二个Suspense组件中,使其与应用程序的其他部分隔离。Suspense组件本身是一个同步组件,所以当它的父级组件被加载时,它就会被加载。

然后它将显示它自己的 fallback 内容,直到5秒结束。

通过这样做,我们可以隔离应用程序中加载较慢的部分,减少我们的首次交互时间。在某些情况下,这可能是必要的,特别是当你需要避免异步瀑布时。

从功能的角度来看,这也是有意义的。你的应用程序的每个功能或 "部分"都可以被包裹在它自己的Suspense组件中,所以每个功能的加载都是一个单一的逻辑单元。

当然,如果你用 "Suspense" 包装每一个组成部分,我们就会回到我们开始的地方。我们可以选择以任何最合理的方式来批处理我们的加载状态。

使用占位符的 Suspense

事例地址: https://codesandbox.io/s/placeholders-and-suspense-k5uzw0?

与其使用单一的 spinner,占位符组件往往可以提供更好的体验。

这种方式向用户展示将要展示的内容,并让他们在界面渲染前有一种期待的感觉。这是 spinner 无法做到的。

可以说--它们很时髦,看起来很酷。因此,我们重构代码,使用占位符方式:

<template>
  <button @click="reload">Reload page</button>
  <Suspense>
    <WithSuspense :time="2000">
      <WithSuspense :time="1500" />
      <WithSuspense :time="1200">
        <WithSuspense :time="1000" />

        <Suspense>
          <WithSuspense :time="5000" />
          <template #fallback>
            <Placeholder />
          </template>
        </Suspense>
      </WithSuspense>
    </WithSuspense>
    <template #fallback>
      <!-- 这里,复制实际数据的形状  -->
      <Placeholder>
        <Placeholder />
        <Placeholder>
          <Placeholder />
          <Placeholder />
        </Placeholder>
      </Placeholder>
    </template>
  </Suspense>
</template>

我们安排了这些Placeholder组件,并对它们进行了风格化处理,使它们看起来与WithSuspense组件完全一样。这提供了一个在加载和装载状态之间的无缝过渡。

在演示中,Placeholder组件在背景上给我们提供了一个CSS动画,以创造一个脉动的效果:

.fast-gradient {
  background: linear-gradient(
    to right,
    rgba(255, 255, 255, 0.1),
    rgba(255, 255, 255, 0.4)
  );
  background-size: 200% 200%;
  animation: gradient 2s ease-in-out infinite;
}

@keyframes gradient {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

总结

爆米花的加载状态是非常明显的,会伤害用户体验。

幸运的是,Suspense 是一个很棒的新特性,它为我们在Vue应用程序中协调加载状态提供了很多选择。

然而,在写这篇文章的时候,Suspense仍然被认为是实验性的,所以要谨慎行事。关于它的状态的最新信息,请参考文档。

(学习视频分享:web前端开发编程基础视频

以上是详解Vue3 Suspense:是什么?能干什么?如何用?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:segmentfault。如有侵权,请联系admin@php.cn删除
了解vue.js:主要是前端框架了解vue.js:主要是前端框架Apr 17, 2025 am 12:20 AM

Vue.js是由尤雨溪在2014年发布的渐进式JavaScript框架,用于构建用户界面。它的核心优势包括:1.响应式数据绑定,数据变化自动更新视图;2.组件化开发,UI可拆分为独立、可复用的组件。

Netflix的前端:React(或VUE)的示例和应用Netflix的前端:React(或VUE)的示例和应用Apr 16, 2025 am 12:08 AM

Netflix使用React作为其前端框架。1)React的组件化开发模式和强大生态系统是Netflix选择它的主要原因。2)通过组件化,Netflix将复杂界面拆分成可管理的小块,如视频播放器、推荐列表和用户评论。3)React的虚拟DOM和组件生命周期优化了渲染效率和用户交互管理。

前端景观:Netflix如何处理其选择前端景观:Netflix如何处理其选择Apr 15, 2025 am 12:13 AM

Netflix在前端技术上的选择主要集中在性能优化、可扩展性和用户体验三个方面。1.性能优化:Netflix选择React作为主要框架,并开发了SpeedCurve和Boomerang等工具来监控和优化用户体验。2.可扩展性:他们采用微前端架构,将应用拆分为独立模块,提高开发效率和系统扩展性。3.用户体验:Netflix使用Material-UI组件库,通过A/B测试和用户反馈不断优化界面,确保一致性和美观性。

React与Vue:Netflix使用哪个框架?React与Vue:Netflix使用哪个框架?Apr 14, 2025 am 12:19 AM

NetflixusesAcustomFrameworkcalled“ Gibbon” BuiltonReact,notReactorVueDirectly.1)TeamExperience:selectBasedAsedonFamiliarity.2)ProjectComplexity:vueforsimplerprojects,vueforsimplerprojects,reactforforforecomplexones.3)cocatizationNeedsneeds:reactofficatizationneedneeds:reactofferizationneedneedneedneeds:reactoffersizatization needeffersefersmoreflexiblesimore.4)ecosyaka

框架的选择:是什么推动了Netflix的决定?框架的选择:是什么推动了Netflix的决定?Apr 13, 2025 am 12:05 AM

Netflix在框架选择上主要考虑性能、可扩展性、开发效率、生态系统、技术债务和维护成本。1.性能与可扩展性:选择Java和SpringBoot以高效处理海量数据和高并发请求。2.开发效率与生态系统:使用React提升前端开发效率,利用其丰富的生态系统。3.技术债务与维护成本:选择Node.js构建微服务,降低维护成本和技术债务。

反应,vue和Netflix前端的未来反应,vue和Netflix前端的未来Apr 12, 2025 am 12:12 AM

Netflix主要使用React作为前端框架,辅以Vue用于特定功能。1)React的组件化和虚拟DOM提升了Netflix应用的性能和开发效率。2)Vue在Netflix的内部工具和小型项目中应用,其灵活性和易用性是关键。

前端中的vue.js:现实世界的应用程序和示例前端中的vue.js:现实世界的应用程序和示例Apr 11, 2025 am 12:12 AM

Vue.js是一种渐进式JavaScript框架,适用于构建复杂的用户界面。1)其核心概念包括响应式数据、组件化和虚拟DOM。2)实际应用中,可以通过构建Todo应用和集成VueRouter来展示其功能。3)调试时,建议使用VueDevtools和console.log。4)性能优化可通过v-if/v-show、列表渲染优化和异步加载组件等实现。

vue.js和React:了解关键差异vue.js和React:了解关键差异Apr 10, 2025 am 09:26 AM

Vue.js适合小型到中型项目,而React更适用于大型、复杂应用。1.Vue.js的响应式系统通过依赖追踪自动更新DOM,易于管理数据变化。2.React采用单向数据流,数据从父组件流向子组件,提供明确的数据流向和易于调试的结构。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)