main.ts
import { createApp, createVNode, render } from "vue";
import App from "./App.vue";
import router from "./router";
import ElementUI from "element-plus";
import "element-plus/dist/index.css";
import loadingBar from "./components/loadingBar.vue"; //导航组件
const vnode = createVNode(loadingBar); //创建虚拟dom
render(vnode, document.body);
const app = createApp(App);
app.use(router);
app.mount("#app");
router.beforeEach((to: any, from: any, next: any) => {
console.log("进入前置路由====");
//开启加载条
vnode.component?.exposed?.startLoading();
next();
});
router.afterEach((to: any, from: any) => {
//关闭加载条
vnode.component?.exposed?.endLoading();
})
;
loadingBar.vue
<template>
<div class="wraps">
<div ref="bar" class="bar"></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;
//性能比定时器好、视觉也比较好
timer.value = window.requestAnimationFrame(function fn() {
if (speed.value < 90) {
dom.style.background = "blue";
speed.value += 1;
dom.style.width = speed.value + "%";
timer.value = window.requestAnimationFrame(fn);
} else {
speed.value = 1;
window.cancelAnimationFrame(timer.value);
}
});
};
onMounted(() => {
startLoading();
endLoading();
});
const endLoading = () => {
let dom = bar.value as HTMLElement;
setTimeout(() => {
window.requestAnimationFrame(() => {
speed.value = 100;
dom.style.width = speed.value + "%";
dom.style.background = "#fff";
});
}, 1000);
};
defineExpose({
startLoading,
endLoading,
});
</script>
<style scoped lang="less">
.wraps {
position: fixed;
top: 0;
width: 100%;
height: 2px;
left: 0;
.bar {
height: inherit;
width: 0;
background: blue;
}
}
</style>
实现效果:
render(vnode, document.body);
是将元素绑定在了body
里面
简记简记~加油Vue3