当前位置: 首页 > news >正文

Vue3 加载条(LoadingBar)

效果如下图:在线预览

在这里插入图片描述

APIs

LoadingBar

参数说明类型默认值必传
containerClass加载条容器的类名stringundefinedfalse
containerStyle加载条容器的样式CSSProperties{}false
loadingBarSize加载条大小,单位 pxnumber2false
colorLoading加载中颜色string‘#1677ff’false
colorFinish加载完成颜色string‘#1677ff’false
colorError加载错误颜色string‘#ff4d4f’false
to加载条的挂载位置,可选:元素标签名(例如 body)或者元素本身string | HTMLElement‘body’false

Methods

名称说明类型
start开始加载的回调函数(from = 0, to = 80) => void
finish结束加载的回调函数() => void
error出现错误的回调函数() => void

创建加载条组件LoadingBar.vue

<script setup lang="ts">
import { ref, nextTick } from 'vue'
import type { CSSProperties } from 'vue'
interface Props {containerClass?: string // 加载条容器的类名containerStyle?: CSSProperties // 加载条容器的样式loadingBarSize?: number // 加载条大小,单位 pxcolorLoading?: string // 加载中颜色colorFinish?: string // 加载完成颜色colorError?: string // 加载错误颜色to?: string | HTMLElement // 加载条的挂载位置,可选:元素标签名(例如 body)或者元素本身
}
withDefaults(defineProps<Props>(), {containerClass: undefined,containerStyle: () => ({}),loadingBarSize: 2,colorLoading: '#1677ff',colorFinish: '#1677ff',colorError: '#ff4d4f',to: 'body'
})
const showLoadingBar = ref(false)
const loadingBarRef = ref() // 加载条 DOM 引用
const loadingStarted = ref(false) // 加载条是否开始
const loadingFinishing = ref(false) // 加载条是否完成
const loadingErroring = ref(false) // 加载条是否报错
async function init() {showLoadingBar.value = falseloadingFinishing.value = falseloadingErroring.value = false
}
async function start(from = 0, to = 80, status: 'starting' | 'error' = 'starting') {// 加载条开始加载的回调函数loadingStarted.value = trueawait init()if (loadingFinishing.value) {return}showLoadingBar.value = trueawait nextTick()if (!loadingBarRef.value) {return}loadingBarRef.value.style.transition = 'none' // 禁用过渡loadingBarRef.value.style.maxWidth = `${from}%`void loadingBarRef.value.offsetWidth // 触发浏览器回流(重排)loadingBarRef.value.className = `loading-bar loading-bar-${status}`loadingBarRef.value.style.transition = ''loadingBarRef.value.style.maxWidth = `${to}%`
}
async function finish() {// 加载条结束加载的回调函数if (loadingFinishing.value || loadingErroring.value) {return}if (loadingStarted.value) {await nextTick()}loadingFinishing.value = trueif (!loadingBarRef.value) {return}loadingBarRef.value.className = 'loading-bar loading-bar-finishing'loadingBarRef.value.style.maxWidth = '100%'void loadingBarRef.value.offsetWidth // 触发浏览器回流(重排)showLoadingBar.value = false
}
function error() {// 加载条出现错误的回调函数if (loadingFinishing.value || loadingErroring.value) {return}if (!showLoadingBar.value) {void start(100, 100, 'error').then(() => {loadingErroring.value = true})} else {loadingErroring.value = trueif (!loadingBarRef.value) {return}loadingBarRef.value.className = 'loading-bar loading-bar-error'loadingBarRef.value.style.maxWidth = '100%'void loadingBarRef.value.offsetWidthshowLoadingBar.value = false}
}
function onAfterEnter() {if (loadingErroring.value) {showLoadingBar.value = false}
}
async function onAfterLeave() {await init()
}
defineExpose({start,finish,error
})
</script>
<template><Teleport :disabled="!to" :to="to"><Transition name="fade-in" @after-enter="onAfterEnter" @after-leave="onAfterLeave"><div v-show="showLoadingBar" class="m-loading-bar-container" :class="containerClass" :style="containerStyle"><divref="loadingBarRef"class="loading-bar":style="`--loading-bar-size: ${loadingBarSize}px; --color-loading: ${colorLoading}; --color-finish: ${colorFinish}; --color-error: ${colorError}; max-width: 100%;`"></div></div></Transition></Teleport>
</template>
<style lang="less" scoped>
.fade-in-enter-active {transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.fade-in-leave-active {transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
.fade-in-enter-from,
.fade-in-leave-to {opacity: 0;
}
.m-loading-bar-container {z-index: 9999;position: fixed;top: 0;left: 0;right: 0;height: var(--loading-bar-size);.loading-bar {width: 100%;transition:max-width 4s linear,background 0.2s linear;height: var(--loading-bar-size);border-radius: var(--loading-bar-size);}.loading-bar-starting {background: var(--color-loading);}.loading-bar-finishing {background: var(--color-finish);transition:max-width 0.2s linear,background 0.2s linear;}.loading-bar-error {background: var(--color-error);transition:max-width 0.2s linear,background 0.2s linear;}
}
</style>

其中引入使用了以下组件:

  • Vue3间距(Space)
  • Vue3按钮(Button)

在要使用的页面引入

<script setup lang="ts">
import LoadingBar from './LoadingBar.vue'
import { ref } from 'vue'
const loadingBar = ref()
const disabled = ref(true)
const localCardRef = ref()
const localLoadingBar = ref()
const customLoadingBar = ref()
function handleStart() {loadingBar.value.start()disabled.value = false
}
function handleFinish() {loadingBar.value.finish()disabled.value = true
}
function handleError() {disabled.value = trueloadingBar.value.error()
}
</script>
<template><div><h1>{{ $route.name }} {{ $route.meta.title }}</h1><h2 class="mt30 mb10">基本使用</h2><Space><Button type="primary" @click="handleStart">开始</Button><Button :disabled="disabled" @click="handleFinish">结束</Button><Button type="danger" @click="handleError">报个错</Button></Space><LoadingBar ref="loadingBar" /><h2 class="mt30 mb10">局部加载条</h2><div class="m-container" ref="localCardRef"><Space><Button type="primary" @click="localLoadingBar.start()">Start</Button><Button @click="localLoadingBar.finish()">Finish</Button><Button type="danger" @click="localLoadingBar.error()">Error</Button></Space></div><LoadingBar ref="localLoadingBar" :container-style="{ position: 'absolute' }" :to="localCardRef" /><h2 class="mt30 mb10">自定义加载条样式</h2><Space><Button type="primary" @click="customLoadingBar.start()">Start</Button><Button @click="customLoadingBar.finish()">Finish</Button><Button type="danger" @click="customLoadingBar.error()">Error</Button></Space><LoadingBarref="customLoadingBar":loading-bar-size="5"color-loading="#2db7f5"color-finish="#52c41a"color-error="magenta"/></div>
</template>
<style lang="less" scoped>
.m-container {position: relative;display: flex;align-items: center;height: 200px;padding: 16px 24px;border: 1px solid #d9d9d9;
}
</style>
http://www.lryc.cn/news/411373.html

相关文章:

  • 《CSS创意项目实战指南》:点亮网页,从实战中掌握CSS的无限创意
  • [FBCTF2019]RCEService (PCRE回溯绕过和%a0换行绕过)
  • vue3后台管理系统 vue3+vite+pinia+element-plus+axios上
  • Mysql的事务隔离级别实现原理
  • 计算机体系结构:缓存一致性ESI
  • log4j2漏洞练习(未完成)
  • 常见网络攻击方法原理、应用场景和防御方法(一)
  • 【leetcode十分钟】覆盖所有点的最少矩形数目(C++思路详解)
  • 【Vue3】默认插槽
  • 华清day4 24-7-31
  • 搜维尔科技:Manus VR数据手套-适用于机器人、人工智能和机器学习解决方案
  • 知识文库杂志知识文库杂志社知识文库编辑部2024年第12期目录
  • 【Linux网络编程】套接字Socket
  • es之must、filter、must_not、should
  • RocketMQ消息发送基本示例(推送消费者)
  • 23 MySQL基本函数、分组查询、多列排序(3)
  • PHP与SEO,应用curl库获取百度下拉关键词案例!
  • MySQL:子查询
  • C++—— IO流
  • vue+node后台处理大文件切片上传--前端部分
  • 【通俗理解】艺术与数学交融
  • 深入探讨 Docker 容器文件系统
  • 《LeetCode热题100》---<4.子串篇三道>
  • 全国区块链职业技能大赛样题第9套前端源码
  • 如何提高编程面试成功率:LeetCode Top 100 问题及解答解析(详细面试宝典)
  • K-近邻和神经网络
  • 用EasyV全景图低成本重现真实场景,360°感受数字孪生
  • 【Golang 面试 - 进阶题】每日 3 题(九)
  • 孟德尔随机化、R语言,报错,如何解决?
  • 一文剖析高可用向量数据库的本质