Hanye官网
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

RouteLoader.vue 2.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. <template>
  2. <Transition name="route-loader">
  3. <div v-if="isLoading" class="route-loader" :style="{ width: `${progress}%` }"></div>
  4. </Transition>
  5. </template>
  6. <script setup lang="ts">
  7. /**
  8. * 路由加载指示器组件
  9. * 在路由切换时显示顶部进度条,提升用户体验
  10. */
  11. import { ref, onMounted, onUnmounted } from 'vue';
  12. import { useRouter } from 'vue-router';
  13. // 加载状态和进度
  14. const isLoading = ref(false);
  15. const progress = ref(0);
  16. const timer = ref<NodeJS.Timeout | null>(null);
  17. const progressTimer = ref<NodeJS.Timeout | null>(null);
  18. // 获取路由器实例
  19. const router = useRouter();
  20. /**
  21. * 开始加载动画
  22. * 显示进度条并逐步增加进度
  23. */
  24. function startLoading() {
  25. // 重置并显示加载条
  26. isLoading.value = true;
  27. progress.value = 0;
  28. // 清除之前可能存在的计时器
  29. if (progressTimer.value) clearInterval(progressTimer.value);
  30. // 创建随机增长的进度条,最多到90%
  31. progressTimer.value = setInterval(() => {
  32. // 根据当前进度计算下一步增长量,进度越高增长越慢
  33. const remaining = 100 - progress.value;
  34. const increment = remaining * 0.1 * Math.random();
  35. // 增加进度,但确保不超过90%
  36. progress.value = Math.min(progress.value + increment, 90);
  37. }, 300);
  38. }
  39. /**
  40. * 完成加载动画
  41. * 将进度迅速增加到100%,然后隐藏进度条
  42. */
  43. function completeLoading() {
  44. // 清除进度增长定时器
  45. if (progressTimer.value) {
  46. clearInterval(progressTimer.value);
  47. progressTimer.value = null;
  48. }
  49. // 完成加载动画,设置100%
  50. progress.value = 100;
  51. // 设置延时以显示完成状态
  52. if (timer.value) clearTimeout(timer.value);
  53. timer.value = setTimeout(() => {
  54. isLoading.value = false;
  55. progress.value = 0;
  56. }, 300);
  57. }
  58. /**
  59. * 监听路由事件
  60. * 在路由切换开始和结束时触发相应的动画
  61. */
  62. onMounted(() => {
  63. // 路由开始切换
  64. router.beforeEach(() => {
  65. startLoading();
  66. return true;
  67. });
  68. // 路由切换完成
  69. router.afterEach(() => {
  70. completeLoading();
  71. });
  72. // 路由切换出错
  73. router.onError(() => {
  74. completeLoading();
  75. });
  76. });
  77. /**
  78. * 组件卸载时清理计时器
  79. */
  80. onUnmounted(() => {
  81. if (timer.value) clearTimeout(timer.value);
  82. if (progressTimer.value) clearInterval(progressTimer.value);
  83. });
  84. </script>