mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-04-03 06:55:06 +08:00
♻️ loading组件重构
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, reactive, ref, useTemplateRef, watch } from "vue";
|
||||
import { computed, onMounted, ref, shallowRef, useTemplateRef, watch } from "vue";
|
||||
|
||||
import type { DialogCheckParams, DialogInputParams, DialogParams } from "./dialog.js";
|
||||
|
||||
@@ -39,7 +39,7 @@ const defaultProp: DialogParams = { title: "", text: "", mode: "check", otcancel
|
||||
const props = defineProps<DialogParams>();
|
||||
|
||||
// 组件参数
|
||||
const data = reactive<DialogParams>(defaultProp);
|
||||
const data = shallowRef<DialogParams>(defaultProp);
|
||||
const show = ref<boolean>(false);
|
||||
const showOuter = ref<boolean>(false);
|
||||
const showInner = ref<boolean>(false);
|
||||
@@ -60,14 +60,17 @@ const inputVal = computed<string | false | undefined>(() => {
|
||||
|
||||
watch(
|
||||
() => show.value,
|
||||
() => {
|
||||
async () => {
|
||||
if (show.value) {
|
||||
showOuter.value = true;
|
||||
setTimeout(() => (showInner.value = true), 100);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 100));
|
||||
showInner.value = true;
|
||||
return;
|
||||
}
|
||||
setTimeout(() => (showInner.value = false), 100);
|
||||
setTimeout(() => (showOuter.value = false), 300);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 100));
|
||||
showInner.value = false;
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 300));
|
||||
showOuter.value = false;
|
||||
},
|
||||
);
|
||||
|
||||
@@ -93,43 +96,51 @@ onMounted(async () => {
|
||||
});
|
||||
|
||||
async function displayCheckBox(params: DialogCheckParams): Promise<boolean | undefined> {
|
||||
data.title = params.title;
|
||||
data.text = params.text ?? "";
|
||||
data.mode = "check";
|
||||
data.otcancel = params.otcancel ?? true;
|
||||
data.value = {
|
||||
title: params.title,
|
||||
text: params.text ?? "",
|
||||
mode: "check",
|
||||
otcancel: params.otcancel ?? true,
|
||||
};
|
||||
show.value = true;
|
||||
return await new Promise<boolean | undefined>((resolve) => {
|
||||
watch(
|
||||
() => show.value,
|
||||
() => setTimeout(() => resolve(checkVal.value), 500),
|
||||
async () => {
|
||||
await new Promise<void>((res) => setTimeout(res, 500));
|
||||
resolve(checkVal.value);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async function displayInputBox(params: DialogInputParams): Promise<string | false | undefined> {
|
||||
data.title = params.title;
|
||||
data.text = params.text ?? "";
|
||||
data.mode = "input";
|
||||
data.value = {
|
||||
title: params.title,
|
||||
text: params.text ?? "",
|
||||
mode: "input",
|
||||
otcancel: params.otcancel ?? true,
|
||||
};
|
||||
inputDefault.value = params.input ?? "";
|
||||
data.otcancel = params.otcancel ?? true;
|
||||
show.value = true;
|
||||
return await new Promise<string | false | undefined>((resolve) => {
|
||||
setTimeout(() => inputEl.value?.focus(), 100);
|
||||
watch(
|
||||
() => show.value,
|
||||
() => setTimeout(() => resolve(inputVal.value), 500),
|
||||
async () => {
|
||||
await new Promise<void>((res) => setTimeout(res, 500));
|
||||
resolve(inputVal.value);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 确认
|
||||
function handleConfirm(): void {
|
||||
if (data.mode === "input") {
|
||||
if (data.value.mode === "input") {
|
||||
dialogVal.value = inputDefault.value;
|
||||
inputDefault.value = "";
|
||||
} else {
|
||||
dialogVal.value = true;
|
||||
}
|
||||
} else dialogVal.value = true;
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
@@ -141,7 +152,7 @@ function handleCancel(): void {
|
||||
|
||||
// 点击外部事件
|
||||
function handleOuter(): void {
|
||||
if (data.otcancel) {
|
||||
if (data.value.otcancel) {
|
||||
dialogVal.value = undefined;
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
@@ -25,14 +25,17 @@ const geetestEl = useTemplateRef<HTMLDivElement>("geetestRef");
|
||||
|
||||
watch(
|
||||
() => show.value,
|
||||
() => {
|
||||
async () => {
|
||||
if (show.value) {
|
||||
showOuter.value = true;
|
||||
setTimeout(() => (showInner.value = true), 100);
|
||||
} else {
|
||||
setTimeout(() => (showInner.value = false), 100);
|
||||
setTimeout(() => (showOuter.value = false), 300);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 100));
|
||||
showInner.value = true;
|
||||
return;
|
||||
}
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 100));
|
||||
showInner.value = false;
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 300));
|
||||
showOuter.value = false;
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file component/func/loading.ts
|
||||
* @description loading 组件封装,函数式调用
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.6.7
|
||||
*/
|
||||
|
||||
import type { ComponentInternalInstance, VNode } from "vue";
|
||||
@@ -11,18 +11,19 @@ import loading from "./loading.vue";
|
||||
|
||||
const loadingId = "tg-func-loading";
|
||||
|
||||
export type LoadingParams = { show: boolean; title: string; subtitle: string; empty?: boolean };
|
||||
export type LoadingParams = { show: boolean; title?: string; subtitle?: string; empty?: boolean };
|
||||
type LoadingUpdateParams = Omit<LoadingParams, "show" | "subtitle"> & { timeout?: number };
|
||||
// 低于100则不可感,高于200则过于缓慢
|
||||
const TIMEOUT: Readonly<number> = 150;
|
||||
|
||||
/**
|
||||
* @description 自定义 loading 组件
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.6.7
|
||||
* @return LoadingInstance
|
||||
*/
|
||||
interface LoadingInstance extends ComponentInternalInstance {
|
||||
exposeProxy: {
|
||||
displayBox: (props: LoadingParams) => void;
|
||||
};
|
||||
}
|
||||
type LoadingInstance = ComponentInternalInstance & {
|
||||
exposeProxy: { displayBox: (props: LoadingParams) => Promise<void> };
|
||||
};
|
||||
|
||||
function renderBox(props: LoadingParams): VNode {
|
||||
const container = document.createElement("div");
|
||||
@@ -35,31 +36,36 @@ function renderBox(props: LoadingParams): VNode {
|
||||
|
||||
let loadingInstance: VNode;
|
||||
|
||||
function showLoadingFull(show: boolean, title: string, sub: string, empty: boolean): void {
|
||||
const params: LoadingParams = { show: show, title: title, subtitle: sub, empty: empty };
|
||||
async function showLoadingFull(option: LoadingParams): Promise<void> {
|
||||
if (loadingInstance !== undefined) {
|
||||
const boxVue = <LoadingInstance>loadingInstance.component;
|
||||
return boxVue.exposeProxy.displayBox(params);
|
||||
return await boxVue.exposeProxy.displayBox(option);
|
||||
} else {
|
||||
loadingInstance = renderBox(params);
|
||||
return showLoadingFull(show, title, sub, empty);
|
||||
loadingInstance = renderBox(option);
|
||||
return await showLoadingFull(option);
|
||||
}
|
||||
}
|
||||
|
||||
function showLoadingStart(title: string, sub?: string): void {
|
||||
showLoadingFull(true, title, sub ?? "", false);
|
||||
async function showLoadingStart(
|
||||
title: string,
|
||||
subtitle?: string,
|
||||
timeout: number = TIMEOUT,
|
||||
): Promise<void> {
|
||||
await showLoadingFull({ show: true, title, subtitle, empty: false });
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, timeout));
|
||||
}
|
||||
|
||||
function showLoadingUpdate(title: string, sub?: string, empty?: boolean): void {
|
||||
showLoadingFull(true, title, sub ?? "", empty ?? false);
|
||||
async function showLoadingUpdate(subtitle: string, opt?: LoadingUpdateParams): Promise<void> {
|
||||
await showLoadingFull({ show: true, title: opt?.title, subtitle, empty: opt?.empty });
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, opt?.timeout ?? TIMEOUT));
|
||||
}
|
||||
|
||||
function showLoadingEmpty(title: string, sub?: string): void {
|
||||
showLoadingFull(true, title, sub ?? "", true);
|
||||
async function showLoadingEmpty(title: string, subtitle?: string): Promise<void> {
|
||||
await showLoadingFull({ show: true, title, subtitle, empty: true });
|
||||
}
|
||||
|
||||
function showLoadingEnd(): void {
|
||||
showLoadingFull(false, "", "", false);
|
||||
async function showLoadingEnd(): Promise<void> {
|
||||
await showLoadingFull({ show: false });
|
||||
}
|
||||
|
||||
const showLoading = {
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
<div />
|
||||
</div>
|
||||
</div>
|
||||
<div class="loading-subtitle" v-show="data.subtitle !== ''">{{ data.subtitle }}</div>
|
||||
<div class="loading-subtitle" v-show="data.subtitle && data.subtitle !== ''">
|
||||
{{ data.subtitle }}
|
||||
</div>
|
||||
<div class="loading-img">
|
||||
<img v-if="!empty" src="/source/UI/loading.webp" alt="loading" />
|
||||
<img v-else src="/source/UI/empty.webp" alt="empty" />
|
||||
@@ -23,7 +25,7 @@
|
||||
</transition>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, onMounted, toRaw } from "vue";
|
||||
import { onMounted, ref, shallowRef, watch } from "vue";
|
||||
|
||||
import { LoadingParams } from "./loading.js";
|
||||
|
||||
@@ -32,36 +34,39 @@ const showOuter = ref<boolean>(false);
|
||||
const showInner = ref<boolean>(false);
|
||||
|
||||
const props = defineProps<LoadingParams>();
|
||||
const data = ref<LoadingParams>(toRaw(props));
|
||||
const data = shallowRef<LoadingParams>(props);
|
||||
|
||||
watch(
|
||||
() => showBox.value,
|
||||
() => {
|
||||
async () => {
|
||||
if (showBox.value) {
|
||||
showOuter.value = true;
|
||||
setTimeout(() => (showInner.value = true), 100);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 100));
|
||||
showInner.value = true;
|
||||
return;
|
||||
}
|
||||
setTimeout(() => (showInner.value = false), 100);
|
||||
setTimeout(() => (showOuter.value = false), 300);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 100));
|
||||
showInner.value = false;
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 300));
|
||||
showOuter.value = false;
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => displayBox(props));
|
||||
onMounted(async () => await displayBox(props));
|
||||
|
||||
function displayBox(params: LoadingParams): void {
|
||||
async function displayBox(params: LoadingParams): Promise<void> {
|
||||
if (!params.show) {
|
||||
showBox.value = false;
|
||||
setTimeout(() => {
|
||||
data.value.title = "";
|
||||
data.value.subtitle = "";
|
||||
data.value.empty = false;
|
||||
}, 500);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 500));
|
||||
data.value = { show: false, title: undefined, subtitle: undefined, empty: undefined };
|
||||
return;
|
||||
}
|
||||
data.value.title = params.title;
|
||||
data.value.subtitle = params.subtitle;
|
||||
data.value.empty = params.empty;
|
||||
data.value = {
|
||||
title: params.title || data.value.title,
|
||||
subtitle: params.subtitle || data.value.subtitle,
|
||||
empty: params.empty || data.value.empty,
|
||||
show: true,
|
||||
};
|
||||
showBox.value = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
</transition>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref, toRaw } from "vue";
|
||||
import { computed, onMounted, onUnmounted, ref, shallowRef } from "vue";
|
||||
|
||||
import { SnackbarParams } from "./snackbar.js";
|
||||
|
||||
const props = defineProps<SnackbarParams>();
|
||||
const data = ref<SnackbarParams>(toRaw(props));
|
||||
const data = shallowRef<SnackbarParams>(props);
|
||||
const show = ref<boolean>(false);
|
||||
const bgColor = computed(() => data.value.color);
|
||||
|
||||
@@ -43,18 +43,31 @@ function transColor(color: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
function displayBox(params: TGApp.Component.Snackbar.Params): void {
|
||||
data.value.text = params.text;
|
||||
data.value.color = transColor(params.color);
|
||||
data.value.timeout = params.timeout;
|
||||
function getTimer(): void {
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
function displayBox(params: SnackbarParams): void {
|
||||
data.value = {
|
||||
text: params.text,
|
||||
color: transColor(params.color),
|
||||
timeout: params.timeout,
|
||||
};
|
||||
show.value = true;
|
||||
if (timer != undefined) {
|
||||
clearTimeout(timer);
|
||||
timer = undefined;
|
||||
}
|
||||
timer = setTimeout(() => (show.value = false), data.value.timeout);
|
||||
timer = setTimeout(getTimer, data.value.timeout);
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer != undefined) {
|
||||
clearTimeout(timer);
|
||||
timer = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
defineExpose({ displayBox });
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
|
||||
Reference in New Issue
Block a user