顶部加载条 vue

<template>
  <div>
    <div class="wraps">
      <div ref="bar" class="bar"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";
let speed = ref<number>(1);
let bar = ref<HTMLElement>();
let timer = ref<number>(0);
const startLoading = () => {
  let dom = bar.value as HTMLElement;
  speed.value = 1;
  window.requestAnimationFrame(function fn() {
    if (speed.value < 90) {
      speed.value += 1;
      dom.style.width = speed.value + "%";
      timer.value = window.requestAnimationFrame(fn);
    } else {
      speed.value = 1;
    }
  });
};
const endLoading = () => {
  let dom = bar.value as HTMLElement;
  setTimeout(() => {
    window.requestAnimationFrame(() => {
      speed.value = 100;
      dom.style.width = speed.value + "%";
    });
  }, 1000);
};
// onMounted(() => {
//   startLoading();
//   endLoading();
// });
defineExpose({
  startLoading,
  endLoading,
});
</script>

<style lang="less">
.wraps {
  position: fixed;
  top: 0;
  width: 100%;
  height: 2px;
  .bar {
    height: inherit;
    width: 0;
    background: #409eff;
  }
}
</style>

main.ts:

import loadingBar from "@/components/loadingBar.vue";
const Vnode = createVNode(loadingBar);
render(Vnode, document.body);


router.beforeEach((to, from, next) => {
  document.title = to.meta.title;
  Vnode.component?.exposed?.startLoading(); 
});
router.afterEach((to, from) => {
  Vnode.component?.exposed?.endLoading();
});

效果图:
在这里插入图片描述