初始版本提交
This commit is contained in:
5
src/components/Loading/index.ts
Normal file
5
src/components/Loading/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import Loading from './src/Loading.vue';
|
||||
|
||||
export { Loading };
|
||||
export { useLoading } from './src/useLoading';
|
||||
export { createLoading } from './src/createLoading';
|
||||
79
src/components/Loading/src/Loading.vue
Normal file
79
src/components/Loading/src/Loading.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<section
|
||||
class="full-loading"
|
||||
:class="{ absolute, [theme]: !!theme }"
|
||||
:style="[background ? `background-color: ${background}` : '']"
|
||||
v-show="loading"
|
||||
>
|
||||
<Spin v-bind="$attrs" :tip="tip" :size="size" :spinning="loading" />
|
||||
</section>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { PropType } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { Spin } from 'ant-design-vue';
|
||||
import { SizeEnum } from '/@/enums/sizeEnum';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Loading',
|
||||
components: { Spin },
|
||||
props: {
|
||||
tip: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
size: {
|
||||
type: String as PropType<SizeEnum>,
|
||||
default: SizeEnum.LARGE,
|
||||
validator: (v: SizeEnum): boolean => {
|
||||
return [SizeEnum.DEFAULT, SizeEnum.SMALL, SizeEnum.LARGE].includes(v);
|
||||
},
|
||||
},
|
||||
absolute: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false,
|
||||
},
|
||||
background: {
|
||||
type: String as PropType<string>,
|
||||
},
|
||||
theme: {
|
||||
type: String as PropType<'dark' | 'light'>,
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.full-loading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 200;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: rgb(240 242 245 / 40%);
|
||||
|
||||
&.absolute {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 300;
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
.full-loading:not(.light) {
|
||||
background-color: @modal-mask-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.full-loading.dark {
|
||||
background-color: @modal-mask-bg;
|
||||
}
|
||||
</style>
|
||||
65
src/components/Loading/src/createLoading.ts
Normal file
65
src/components/Loading/src/createLoading.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import { VNode, defineComponent } from 'vue';
|
||||
import type { LoadingProps } from './typing';
|
||||
|
||||
import { createVNode, render, reactive, h } from 'vue';
|
||||
import Loading from './Loading.vue';
|
||||
|
||||
export function createLoading(props?: Partial<LoadingProps>, target?: HTMLElement, wait = false) {
|
||||
let vm: Nullable<VNode> = null;
|
||||
const data = reactive({
|
||||
tip: '',
|
||||
loading: true,
|
||||
...props,
|
||||
});
|
||||
|
||||
const LoadingWrap = defineComponent({
|
||||
render() {
|
||||
return h(Loading, { ...data });
|
||||
},
|
||||
});
|
||||
|
||||
vm = createVNode(LoadingWrap);
|
||||
|
||||
if (wait) {
|
||||
// TODO fix https://github.com/anncwb/vue-vben-admin/issues/438
|
||||
setTimeout(() => {
|
||||
render(vm, document.createElement('div'));
|
||||
}, 0);
|
||||
} else {
|
||||
render(vm, document.createElement('div'));
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (vm?.el && vm.el.parentNode) {
|
||||
vm.el.parentNode.removeChild(vm.el);
|
||||
}
|
||||
}
|
||||
|
||||
function open(target: HTMLElement = document.body) {
|
||||
if (!vm || !vm.el) {
|
||||
return;
|
||||
}
|
||||
target.appendChild(vm.el as HTMLElement);
|
||||
}
|
||||
|
||||
if (target) {
|
||||
open(target);
|
||||
}
|
||||
return {
|
||||
vm,
|
||||
close,
|
||||
open,
|
||||
setTip: (tip: string) => {
|
||||
data.tip = tip;
|
||||
},
|
||||
setLoading: (loading: boolean) => {
|
||||
data.loading = loading;
|
||||
},
|
||||
get loading() {
|
||||
return data.loading;
|
||||
},
|
||||
get $el() {
|
||||
return vm?.el as HTMLElement;
|
||||
},
|
||||
};
|
||||
}
|
||||
10
src/components/Loading/src/typing.ts
Normal file
10
src/components/Loading/src/typing.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { SizeEnum } from '/@/enums/sizeEnum';
|
||||
|
||||
export interface LoadingProps {
|
||||
tip: string;
|
||||
size: SizeEnum;
|
||||
absolute: boolean;
|
||||
loading: boolean;
|
||||
background: string;
|
||||
theme: 'dark' | 'light';
|
||||
}
|
||||
49
src/components/Loading/src/useLoading.ts
Normal file
49
src/components/Loading/src/useLoading.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { unref } from 'vue';
|
||||
import { createLoading } from './createLoading';
|
||||
import type { LoadingProps } from './typing';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
export interface UseLoadingOptions {
|
||||
target?: any;
|
||||
props?: Partial<LoadingProps>;
|
||||
}
|
||||
|
||||
interface Fn {
|
||||
(): void;
|
||||
}
|
||||
|
||||
export function useLoading(props: Partial<LoadingProps>): [Fn, Fn, (string) => void];
|
||||
export function useLoading(opt: Partial<UseLoadingOptions>): [Fn, Fn, (string) => void];
|
||||
|
||||
export function useLoading(
|
||||
opt: Partial<LoadingProps> | Partial<UseLoadingOptions>,
|
||||
): [Fn, Fn, (string) => void] {
|
||||
let props: Partial<LoadingProps>;
|
||||
let target: HTMLElement | Ref<ElRef> = document.body;
|
||||
|
||||
if (Reflect.has(opt, 'target') || Reflect.has(opt, 'props')) {
|
||||
const options = opt as Partial<UseLoadingOptions>;
|
||||
props = options.props || {};
|
||||
target = options.target || document.body;
|
||||
} else {
|
||||
props = opt as Partial<LoadingProps>;
|
||||
}
|
||||
|
||||
const instance = createLoading(props, undefined, true);
|
||||
|
||||
const open = (): void => {
|
||||
const t = unref(target as Ref<ElRef>);
|
||||
if (!t) return;
|
||||
instance.open(t);
|
||||
};
|
||||
|
||||
const close = (): void => {
|
||||
instance.close();
|
||||
};
|
||||
|
||||
const setTip = (tip: string) => {
|
||||
instance.setTip(tip);
|
||||
};
|
||||
|
||||
return [open, close, setTip];
|
||||
}
|
||||
Reference in New Issue
Block a user