vue3-内置组件-Suspense

news/2024/7/10 2:18:38 标签: vue.js, javascript, 前端, vue

Suspense (实验性功能)

<Suspense> 是一项实验性功能。它不一定会最终成为稳定功能,并且在稳定之前相关 API 也可能会发生变化。

<Suspense> 是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。

异步依赖

要了解 <Suspense> 所解决的问题和它是如何与异步依赖进行交互的,我们需要想象这样一种组件层级结构:

<Suspense>
└─ <Dashboard>
   ├─ <Profile>
   │  └─ <FriendStatus>(组件有异步的 setup())
   └─ <Content>
      ├─ <ActivityFeed> (异步组件)
      └─ <Stats>(异步组件)

在这个组件树中有多个嵌套组件,要渲染出它们,首先得解析一些异步资源。如果没有 <Suspense>,则它们每个都需要处理自己的加载、报错和完成状态。在最坏的情况下,我们可能会在页面上看到三个旋转的加载态,在不同的时间显示出内容。

有了 <Suspense> 组件后,我们就可以在等待整个多层级组件树中的各个异步依赖获取结果时,在顶层展示出加载中或加载失败的状态。

<Suspense> 可以等待的异步依赖有两种:

  1. 带有异步 setup() 钩子的组件。这也包含了使用 <script setup> 时有顶层 await 表达式的组件。

  2. 异步组件。

async setup()

如果使用 <script setup>,那么顶层 await 表达式会自动让该组件成为一个异步依赖:

export default {
  async setup() {
    const res = await fetch(...)
    const posts = await res.json()
    return {
      posts
    }
  }
}

如果使用 <script setup>,那么顶层 await 表达式会自动让该组件成为一个异步依赖:

<script setup>
const res = await fetch(...)
const posts = await res.json()
</script>

<template>
  {{ posts }}
</template>
异步组件

步组件默认就是“suspensible”的。这意味着如果组件关系链上有一个 <Suspense>,那么这个异步组件就会被当作这个 <Suspense> 的一个异步依赖。在这种情况下,加载状态是由 <Suspense> 控制,而该组件自己的加载、报错、延时和超时等选项都将被忽略。

异步组件也可以通过在选项中指定 suspensible: false 表明不用 Suspense 控制,并让组件始终自己控制其加载状态。

加载中状态

<Suspense> 组件有两个插槽:#default 和 #fallback。两个插槽都只允许一个直接子节点。在可能的时候都将显示默认槽中的节点。否则将显示后备槽中的节点。

<Suspense>
  <!-- 具有深层异步依赖的组件 -->
  <Dashboard />

  <!-- 在 #fallback 插槽中显示 “正在加载中” -->
  <template #fallback>
    Loading...
  </template>
</Suspense>

在初始渲染时,<Suspens> 将在内存中渲染其默认的插槽内容。如果在这个过程中遇到任何异步依赖,则会进入挂起状态。在挂起状态期间,展示的是后备内容。当所有遇到的异步依赖都完成后<Suspens> 会进入完成状态,并将展示出默认插槽的内容。

如果在初次渲染时没有遇到异步依赖<Suspense> 会直接进入完成状态。

进入完成状态后,只有当默认插槽的根节点被替换时 <Suspense> 才会回到挂起状态。组件树中新的更深层次的异步依赖不会造成 <Suspense> 回退到挂起状态。

发生回退时,后备内容不会立即展示出来。相反,<Suspense> 在等待新内容和异步依赖完成时,会展示之前 #default 插槽的内容。这个行为可以通过一个 timeout prop 进行配置:在等待渲染新内容耗时超过 timeout 之后,<Suspense> 将会切换为展示后备内容。若 timeout 值为 0 将导致在替换默认内容时立即显示后备内容。

事件

<Suspense> 组件会触发三个事件:pending、resolve 和 fallback。pending 事件是在进入挂起状态时触发。resolve 事件是在 default 插槽完成获取新内容时触发。fallback 事件则是在 fallback 插槽的内容显示时触发。

例如,可以使用这些事件在加载新组件时在之前的 DOM 最上层显示一个加载指示器。

错误处理

<Suspense> 组件自身目前还不提供错误处理,不过你可以使用 errorCaptured 选项或者 onErrorCaptured() 钩子,在使用到 <Suspense> 的父组件中捕获和处理异步错误。

和其他组件结合

我们常常会将 <Suspense> 和 <Transition>、<KeepAlive> 等组件结合。要保证这些组件都能正常工作,嵌套的顺序非常重要。 另外,这些组件都通常与 Vue Router 中的 <RouterView> 组件结合使用。

下面的示例展示了如何嵌套这些组件,使它们都能按照预期的方式运行。若想组合得更简单,你也可以删除一些你不需要的组件:

<RouterView v-slot="{ Component }">
  <template v-if="Component">
    <Transition mode="out-in">
      <KeepAlive>
        <Suspense>
          <!-- 主要内容 -->
          <component :is="Component"></component>

          <!-- 加载中状态 -->
          <template #fallback>
            正在加载...
          </template>
        </Suspense>
      </KeepAlive>
    </Transition>
  </template>
</RouterView>

Vue Router 使用动态导入对懒加载组件进行了内置支持。这些与异步组件不同,目前他们不会触发 <Suspense>。但是,它们仍然可以有异步组件作为后代,这些组件可以照常触发 <Suspense>。

示例:模拟加载两个异步组件最终同步渲染:

子组件 1 promise 形式

组件 1 模拟文本内容 2 秒后变更值

<script lang="ts" setup>
import { ref } from 'vue'

const result = ref(0)

const init = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      result.value = 123
      return resolve({
        result
      })
    }, 3000)
  })
}
await init()
</script>

<template>
  <div class="container">
    <h1>{{ result }}</h1>
  </div>
</template>

<style lang="scss" scoped>
.container {
}
</style>

组件 2 模拟网络请求获取图片

<script lang="ts" setup>
import { ref } from 'vue'

import axios from 'axios'

const rowData = ref<any>()
rowData.value = await axios.get('https://dog.ceo/api/breeds/image/random')
</script>

<template>
  <div class="container">
    <div>
      <img class="img" :src="rowData && rowData?.data.message" alt="" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.container {
  img {
    width: 200px;
    height: 100px;
  }
}
</style>

父组件异步加载两个组件

<script lang="ts" setup>
import { ref } from 'vue'
import Com25_1 from '@/components/demo/Com25-1.vue'
import Com25_2 from '@/components/demo/Com25-2.vue'
</script>

<template>
  <div class="container">
    <h1>suspense 示例</h1>
    <Suspense>
      <div>
        <Com25_1></Com25_1>
        <Com25_2></Com25_2>
      </div>
      <!-- 在 #fallback 插槽中显示 “Loading...”  或者显示一个骨架屏 -->
      <template #fallback>显示 Loading... 或者显示一个骨架屏幕</template>
    </Suspense>
  </div>
</template>

<style lang="scss" scoped>
.container {
}
</style>

组件 1 需要两秒才会执行完成

组件 2 网络请求图片执行时间 (根据网络速度和服务器响应)

只有当都完成请求时 才会正常显示内容。

效果:


http://www.niftyadmin.cn/n/5374761.html

相关文章

【Java程序设计】【C00265】基于Springboot的地方废物回收机制管理系统(有论文)

基于Springboot的地方废物回收机制管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的地方废物回收机构管理系统 本系统分为管理员功能模块以及员工功能模块。 管理员功能模块&#xff1a;管理员登录系统后…

《Linux 简易速速上手小册》第8章: 安全性与加固(2024 最新版)

文章目录 8.1 防火墙与安全策略8.1.1 重点基础知识8.1.2 重点案例&#xff1a;配置 iptables 以保护 Web 服务器8.1.3 拓展案例 1&#xff1a;使用 firewalld 配置动态防御区域8.1.4 拓展案例 2&#xff1a;配置 ufw 以简化管理 8.2 SSH 安全最佳实践8.2.1 重点基础知识8.2.2 重…

【C语言】实现双向链表

目录 &#xff08;一&#xff09;头文件 &#xff08;二&#xff09; 功能实现 &#xff08;1&#xff09;初始化 &#xff08;2&#xff09;打印链表 &#xff08;3&#xff09; 头插与头删 &#xff08;4&#xff09;尾插与尾删 &#xff08;5&#xff09;指定位置之后…

HeidiSQL安装配置(基于小皮面板(phpstudy))连接MySQL

下载资源 对于这款图形化工具&#xff0c;博主建议通过小皮面板&#xff08;phpstudy&#xff09;来下载即可&#xff0c;也是防止你下载到钓鱼软件&#xff0c;小皮面板&#xff08;phpstudy&#xff09;如果你不懂是什么&#xff0c;请看下面链接这篇博客 第二篇&#xff1a;…

【实战】一、Jest 前端自动化测试框架基础入门 —— 前端要学的测试课 从Jest入门到TDD BDD双实战(一)

文章目录 一、前端要学的测试课1.前端要学的测试2.前端工程化的一部分3.前端自动化测试的例子4.前端为什么需要自动化测试&#xff1f;5.课程涵盖内容6.前置技能7.学习收获 二、Jest 前端自动化测试框架基础入门1. 自动化测试背景及原理前端自动化测试产生的背景及原理 2.前端自…

mac无法往硬盘里存东西 Mac硬盘读不出来怎么办 Mac硬盘格式 硬盘检测工具

mac有时候会出现一些问题&#xff0c;比如无法往硬盘里存东西&#xff0c;或者无法往硬盘上拷贝文件。这些问题会给用户带来很大的困扰&#xff0c;影响正常的工作和学习。那么&#xff0c;mac无法往硬盘里存东西&#xff0c;mac无法往硬盘上拷贝怎么办呢&#xff1f;软妹子将为…

STM32 7-8

目录 ADC AD单通道 AD多通道 DMA DMA转运数据 DMAAD多通道 ADC AD单通道 AD.c #include "stm32f10x.h" // Device header/*** brief 初始化AD所需要的所有设备* param 无* retval 无*/ void AD_Init(void) {RCC_APB2PeriphClockCmd(RCC_AP…

《统计学简易速速上手小册》第10章:案例研究和未来趋势(2024 最新版)

文章目录 10.1 统计学成功案例分析10.1.1 基础知识10.1.2 主要案例&#xff1a;药物临床试验10.1.3 拓展案例 1&#xff1a;市场趋势分析10.1.4 拓展案例 2&#xff1a;社会行为研究 10.2 统计学的伦理考量10.2.1 基础知识10.2.2 主要案例&#xff1a;个性化医疗研究10.2.3 拓展…