全局前置守卫
每当有路由进行跳转前,都会执行全局前置守卫的逻辑
/router/index.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import { createRouter, createWebHistory } from "vue-router" import type { RouteRecordRaw } from "vue-router"
const routes: Array<RouteRecordRaw> = [ { path: "/", component: ()=> import("@/components/Login.vue") }, { path: "/index", component: ()=> import("@/components/Index.vue") } ]
const router = createRouter({ history: createWebHistory(), routes })
const whiteList = ["/"]
router.beforeEach((to,from,next)=> { if(whiteList.includes(to.path) || localStorage.getItem("token")) { next() } else { next("/") } })
export default router
|
Login.vue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| <template> <div class="login"> <el-card class="box-card"> <el-form ref="form" :model="formInline" :rules="rules" class="demo-form-inline"> <el-form-item prop="user" label="账号"> <el-input v-model="formInline.user" placeholder="请输入账号" clearable /> </el-form-item> <el-form-item prop="password" label="密码"> <el-input type="password" v-model="formInline.password" placeholder="请输入密码"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">登录</el-button> </el-form-item> </el-form> </el-card> </div> </template>
<script setup lang="ts"> import { ref, reactive } from 'vue' import { useRouter } from "vue-router" import { ElMessage } from "element-plus" import type { FormItemRule, FormInstance } from "element-plus"
const router = useRouter()
type Form = { user: string password: string }
type Rules = { // 遍历Form类型的key [K in keyof Form]?: Array<FormItemRule> }
const formInline = reactive<Form>({ user: '', password: '', })
const form = ref<FormInstance>() const rules: Rules = { user: [ { // 必填 required: true, // 填写不合规时的提示信息 message: "必须输入账号", // 类型 type: "string", // 触发的条件 // trigger: "change" } ], password: [ { required: true, message: "必须输入密码", type: "string", } ] }
const onSubmit = () => { form.value?.validate((validate)=> { console.log(validate) // 验证是否通过 if(validate) { router.push("/index") localStorage.setItem("token", "114514") } else { ElMessage.error("请检查输入") } }) } </script>
<style scoped lang="scss"> .login { height: 100%; display: flex; justify-content: center; align-items: center; } </style>
|
Index.vue:
1 2 3 4 5
| <template> <div> 登陆成功 </div> </template>
|
全局后置守卫
每当有路由进行跳转后,都会执行全局后置守卫的逻辑
后置守卫相比前置守卫,没有next函数,也不改变导航
/router/index.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import { createRouter, createWebHistory } from "vue-router" import type { RouteRecordRaw } from "vue-router" import { createVNode, render } from "vue" import LoadingBar from "@/components/LoadingBar.vue"
const Vnode = createVNode(LoadingBar)
render(Vnode, document.body)
const routes: Array<RouteRecordRaw> = [ { path: "/", component: ()=> import("@/components/Login.vue") }, { path: "/index", component: ()=> import("@/components/Index.vue") } ]
const router = createRouter({ history: createWebHistory(), routes })
const whiteList = ["/"]
router.beforeEach((to,from,next)=> { Vnode.component?.exposed?.startLoading() if(whiteList.includes(to.path) || localStorage.getItem("token")) { next() } else { next("/") } })
router.afterEach((to,from)=> { Vnode.component?.exposed?.endLoading() })
export default router
|
LoadingBar.vue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| <template> <div class="wraps"> <div ref="bar" class="bar"></div> </div> </template>
<script setup lang="ts"> import { ref } from "vue"
let bar = ref<HTMLElement>() let speed = ref<number>(1) let timer = ref<number>(0)
const startLoading = () => { let dom = bar.value as HTMLElement speed.value = 1 // requestAnimationFrame动画帧 回调函数只会执行一次 timer.value = window.requestAnimationFrame(function fn() { console.log(speed.value, 1) if (speed.value < 90) { speed.value++ dom.style.width = speed.value + "%" // 递归requestAnimationFrame 执行动画 timer.value = window.requestAnimationFrame(fn) } else { speed.value = 1 window.cancelAnimationFrame(timer.value) } }) }
const endLoading = () => { let dom = bar.value as HTMLElement window.setTimeout(() => { window.requestAnimationFrame(() => { speed.value = 100 dom.style.width = speed.value + "%" }) }, 200)
}
defineExpose({ startLoading, endLoading }) </script>
<style scoped lang="scss"> .wraps { position: fixed; top: 0; width: 100%; height: 2px;
.bar { height: inherit; width: 0; background-color: blue; } } </style>
|