08.b-全局后置守卫案例-进度条加载

Huxzhi大约 2 分钟vue3

src/main.ts

import { createApp, createVNode, render } from 'vue'
// import './style.css'
import App from './App.vue'
import router from './router'
import ElementUi from 'element-plus'
import 'element-plus/dist/index.css'
import loadingBarVue from './components/loadingBar.vue'

console.log(loadingBarVue); //不能直接使用
const Vnode = createVNode(loadingBarVue) //转成虚拟Dom
render(Vnode, document.body) //挂载


const app = createApp(App)


const whiteList = ['/']

//全局前置守卫
router.beforeEach((to, from, next) => {

  Vnode.component?.exposed?.startLoading() //loadingBar

  let token = localStorage.getItem('token')
  //白名单 有值 或者登陆过存储了token信息可以跳转 否则就去登录页面
  if (whiteList.includes(to.path) || token) { //token每次都要跟后端校验一下是否过期
  }
})

//全局后置守卫
router.afterEach((to, from) => {
  Vnode.component?.exposed?.endLoading()
})

app.mount('#app')

src/components/loadingBar.vue

<template>

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

</template>

<script setup lang='ts'>
import { ref, reactive, onMounted } from 'vue'

let speed = ref<number>(1)
let bar = ref<HTMLElement>()
let timer = ref<number>(0) //设置id

const startLoading = () => {
  let dom = bar.value as HTMLElement
  speed.value = 1
  console.log(dom);
  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(() => {
    window.requestAnimationFrame(() => {
      speed.value = 100;
      dom.style.width = speed.value + '%'
    })
  }, 1000)


}
// 放到全局导航守卫-后置守卫 后不需要了
// //只有在 onMounted 之后才能获取 DOM
// onMounted(() => {
//   startLoading()
//   endLoading()
// })

defineExpose({
  startLoading,
  endLoading,
})

</script>

<style lang='less' scoped>
.wraps {
  position: fixed;
  top: 0;
  width: 100%;
  height: 2px;

  .bar {
    height: inherit;
    width: 0;
    background: blue;
  }
}
</style>

js 动画渲染补充

javascript 动画-计时器-requestAnimationFrame

src/views/Login.vue

看看效果,最好是放到 全局导航守卫-后置守卫

<template>
  <!-- <loadingBar></loadingBar> 这里只是看看效果,最好是放到 全局导航守卫-后置守卫 !!!-->
  <div class="login">

    <el-form ref="form" :rules="rules" :model="formInline" class="demo-form-inline">
      <el-form-item prop="user" label="账号:">
        <el-input v-model="formInline.user" placeholder="请输入账号" />
import { useRouter } from 'vue-router'
import router from '../router';
import { ElMessage, FormRules, FormInstance } from 'element-plus'
import loadingBar from '../components/loadingBar.vue';

const formInline = reactive({
  user: '',