自定义进度条组件
把组件模板通过转换成虚拟dom,再挂载到body中
路由前置和后置守卫分别触发组件暴露出来的方法
组件模板及方法
<template>
<div class="warps">
<div ref="bar" class="bar"></div>
</div>
</template>
<script setup lang='ts'>
import { ref } from "vue"
const bar = ref<HTMLElement>()
let speed = ref<number>(1)
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){
speed.value+=1;
dom.style.width = speed.value + '%'
timer.value=window.requestAnimationFrame(fn)
}else{
speed.value = 1
window.cancelAnimationFrame(timer.value)
}
})
}
const endLoading = () => { //路由加载结束
let dom = bar.value as HTMLElement;
setTimeout(()=>{
speed.value = 0;
dom.style.width = '0%'
},1000)
}
defineExpose({ //暴露组件的两个方法
startLoading,
endLoading
})
</script>
<style lang="scss" scoped>
.warps {
position: fixed;
top: 0px;
height: 2px;
width: 100%;
.bar {
height: 10px;
width: 0;
background-color: pink;
}
}
</style>
转虚拟dom并挂载
工具类util
import { createVNode,render } from 'vue'
import loadingBar from '../components/loadingBar.vue'
const vnode = createVNode(loadingBar) //转虚拟dom
render(vnode,document.body) //挂载
export default vnode
前置路由和后置路由
import router from './router'
import vnode from './util'
router.beforeEach((to, from, next) => {
vnode.component?.exposed?.startLoading() //使用组件暴露出来的方法
next()
})
router.afterEach((to, from) => {
vnode.component?.exposed?.endLoading() //使用组件暴露出来的方法
})