mirror of
https://github.com/un-pany/v3-admin-vite.git
synced 2025-04-20 19:09:21 +08:00
feat: 封装全屏 loading hook (#41)
This commit is contained in:
parent
9860c9a8e1
commit
b9b917cf5e
@ -1,6 +1,3 @@
|
||||
// import { request } from "@/utils/service"
|
||||
|
||||
/** 查 */
|
||||
export function getRemoteSelectData() {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
@ -33,3 +30,24 @@ export function getRemoteSelectData() {
|
||||
}, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
export interface IBirdsItem {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export const getBirds = () => {
|
||||
return new Promise<IBirdsItem[]>((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve([...Array(5)].map((_t, index) => ({ id: index, name: `t${index}` })))
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
||||
export const getCars = (id: number) => {
|
||||
return new Promise((_resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error("sorry" + id))
|
||||
}, 1000)
|
||||
})
|
||||
}
|
60
src/hooks/useFullscreenLoading.ts
Normal file
60
src/hooks/useFullscreenLoading.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { ElLoading, LoadingOptions } from "element-plus"
|
||||
|
||||
const defaultOption = {
|
||||
lock: true,
|
||||
text: "加载中...",
|
||||
background: "rgba(0, 0, 0, 0.7)"
|
||||
}
|
||||
|
||||
interface ILoading {
|
||||
close: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入一个方法 fn,在它执行周期内,加上「全屏」loading
|
||||
* 如果:
|
||||
* 1. fn 是同步方法,结束后隐藏 loading
|
||||
* 2. 如果是异步方法,resolve 后隐藏 loading
|
||||
* 3. 报错后隐藏 loading 并抛出错误
|
||||
* @param {*} fn 函数
|
||||
* @param options
|
||||
* @returns Function 一个新的函数,去执行它吧
|
||||
*/
|
||||
export const useFullscreenLoading = <T>(
|
||||
fn: (...args: any[]) => T,
|
||||
options: LoadingOptions = {}
|
||||
): ((...args: any[]) => Promise<T>) => {
|
||||
let loading: ILoading | undefined
|
||||
const showLoading = (options: LoadingOptions) => {
|
||||
loading = ElLoading.service(options)
|
||||
}
|
||||
|
||||
const hideLoading = () => {
|
||||
loading && loading.close()
|
||||
}
|
||||
const _options = { ...defaultOption, ...options }
|
||||
const newFn = (...args: any[]) => {
|
||||
try {
|
||||
showLoading(_options)
|
||||
const result = fn(...args)
|
||||
const isPromise = result instanceof Promise
|
||||
if (!isPromise) {
|
||||
hideLoading()
|
||||
return Promise.resolve(result)
|
||||
}
|
||||
return result
|
||||
.then((res: any) => {
|
||||
hideLoading()
|
||||
return res
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
hideLoading()
|
||||
throw err
|
||||
})
|
||||
} catch (err) {
|
||||
hideLoading()
|
||||
throw err
|
||||
}
|
||||
}
|
||||
return newFn
|
||||
}
|
@ -190,16 +190,30 @@ export const constantRoutes: RouteRecordRaw[] = [
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "/select",
|
||||
path: "/hooks",
|
||||
component: Layout,
|
||||
redirect: "/hooks/use-fetch-select",
|
||||
name: "Hooks",
|
||||
meta: {
|
||||
title: "hooks",
|
||||
elIcon: "Menu",
|
||||
alwaysShow: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: () => import("@/views/select/index.vue"),
|
||||
name: "Select",
|
||||
path: "use-fetch-select",
|
||||
component: () => import("@/views/hooks/use-fetch-select.vue"),
|
||||
name: "UseFetchSelect",
|
||||
meta: {
|
||||
title: "下拉框",
|
||||
svgIcon: "component"
|
||||
title: "useFetchSelect"
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "use-fullscreen-loading",
|
||||
component: () => import("@/views/hooks/use-fullscreen-loading.vue"),
|
||||
name: "UseFullscreenLoading",
|
||||
meta: {
|
||||
title: "useFullscreenLoading"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup name="Select" lang="ts">
|
||||
import { getRemoteSelectData } from "@/api/select"
|
||||
import { getRemoteSelectData } from "@/api/mock"
|
||||
import { useFetchSelect } from "@/hooks/useFetchSelect"
|
||||
|
||||
const { loading, options, selectedValue } = useFetchSelect({
|
41
src/views/hooks/use-fullscreen-loading.vue
Normal file
41
src/views/hooks/use-fullscreen-loading.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-button @click="querySuccess">查询成功</el-button>
|
||||
<el-button @click="queryFailed">查询失败</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getBirds, getCars, type IBirdsItem } from "@/api/mock"
|
||||
import { useFullscreenLoading } from "@/hooks/useFullscreenLoading"
|
||||
import { ElMessage } from "element-plus"
|
||||
|
||||
const querySuccess = async () => {
|
||||
const birds = await useFullscreenLoading(getBirds)()
|
||||
ElMessage.success(birds.map((t: IBirdsItem) => t.name).join())
|
||||
}
|
||||
|
||||
const svg = `
|
||||
<path class="path" d="
|
||||
M 30 15
|
||||
L 28 17
|
||||
M 25.61 25.61
|
||||
A 15 15, 0, 0, 1, 15 30
|
||||
A 15 15, 0, 1, 1, 27.99 7.5
|
||||
L 15 15
|
||||
" style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
|
||||
`
|
||||
|
||||
const queryFailed = async () => {
|
||||
try {
|
||||
await useFullscreenLoading(getCars, {
|
||||
text: "自定义加载文字",
|
||||
background: "rgba(255, 214, 210, 0.7)",
|
||||
svg,
|
||||
svgViewBox: "-10, -10, 50, 50"
|
||||
})(233)
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err.message)
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user