1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- <template>
- <Transition name="route-loader">
- <div v-if="isLoading" class="route-loader" :style="{ width: `${progress}%` }"></div>
- </Transition>
- </template>
-
- <script setup lang="ts">
- /**
- * 路由加载指示器组件
- * 在路由切换时显示顶部进度条,提升用户体验
- */
- import { ref, onMounted, onUnmounted } from 'vue';
- import { useRouter } from 'vue-router';
-
- // 加载状态和进度
- const isLoading = ref(false);
- const progress = ref(0);
- const timer = ref<NodeJS.Timeout | null>(null);
- const progressTimer = ref<NodeJS.Timeout | null>(null);
-
- // 获取路由器实例
- const router = useRouter();
-
- /**
- * 开始加载动画
- * 显示进度条并逐步增加进度
- */
- function startLoading() {
- // 重置并显示加载条
- isLoading.value = true;
- progress.value = 0;
-
- // 清除之前可能存在的计时器
- if (progressTimer.value) clearInterval(progressTimer.value);
-
- // 创建随机增长的进度条,最多到90%
- progressTimer.value = setInterval(() => {
- // 根据当前进度计算下一步增长量,进度越高增长越慢
- const remaining = 100 - progress.value;
- const increment = remaining * 0.1 * Math.random();
-
- // 增加进度,但确保不超过90%
- progress.value = Math.min(progress.value + increment, 90);
- }, 300);
- }
-
- /**
- * 完成加载动画
- * 将进度迅速增加到100%,然后隐藏进度条
- */
- function completeLoading() {
- // 清除进度增长定时器
- if (progressTimer.value) {
- clearInterval(progressTimer.value);
- progressTimer.value = null;
- }
-
- // 完成加载动画,设置100%
- progress.value = 100;
-
- // 设置延时以显示完成状态
- if (timer.value) clearTimeout(timer.value);
- timer.value = setTimeout(() => {
- isLoading.value = false;
- progress.value = 0;
- }, 300);
- }
-
- /**
- * 监听路由事件
- * 在路由切换开始和结束时触发相应的动画
- */
- onMounted(() => {
- // 路由开始切换
- router.beforeEach(() => {
- startLoading();
- return true;
- });
-
- // 路由切换完成
- router.afterEach(() => {
- completeLoading();
- });
-
- // 路由切换出错
- router.onError(() => {
- completeLoading();
- });
- });
-
- /**
- * 组件卸载时清理计时器
- */
- onUnmounted(() => {
- if (timer.value) clearTimeout(timer.value);
- if (progressTimer.value) clearInterval(progressTimer.value);
- });
- </script>
|