导航守卫
# 导航守卫
文档:导航守卫 | Vue Router (vuejs.org) (opens new window)
# 导航守卫
笔记
通过导航守卫,决定我们当前需要跳转到哪个页面以及是否要进行当前的跳转
主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
# 全局前置守卫
笔记
在进行跳转之前,被进行激活的守卫
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
# 参数
接收两个参数:
to
: 要去哪个路由from
: 从哪个路由中来
可选第三个参数:
next
: 是否要跳转到当前的路由之中
router.beforeEach((to, from, next) => {
// 1.用户已登录,则不允许进入login
// 2.用户未登录,只允许进入login
// if (store.state.user.token){} 制订快捷访问
if (store.getters.token) {
// 1,用户已登录,则不允许进入login
if (to.path === '/login') {
next('/')
} else {
next()
}
} else {
// 2.用户未登录,只允许进入login
if (whiteList.indexOf(to.path) > -1) {
next()
} else {
next('/login')
}
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 全局后置守卫
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next
函数也不会改变导航本身:
实例
使用场景一般可以用来做loadingBar
router.afterEach((to,from)=>{
Vnode.component?.exposed?.endLoading()
})
1
2
3
2
3
点击查看
loadingBar
组件
<template>
<div class="wraps">
<div ref="bar" class="bar"></div>
</div>
</template>
<script setup lang='ts'>
import { ref, onMounted } 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() {
// 递归到90
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)
}
})
}
// 结束的时候变为100
const endLoading = () => {
let dom = bar.value as HTMLElement;
setTimeout(() => {
window.requestAnimationFrame(() => {
speed.value = 100;
dom.style.width = speed.value + '%'
})
}, 500)
}
// 暴露出去
defineExpose({
startLoading,
endLoading
})
</script>
<style scoped lang="less">
.wraps {
position: fixed;
top: 0;
width: 100%;
height: 2px;
.bar {
height: inherit;
width: 0;
background: blue;
}
}
</style>
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
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
mian.ts
import { createApp, createVNode, render } from 'vue'
import loadingBar from './components/loadingBar.vue'
// 转成虚拟DOM
const Vnode = createVNode(loadingBar)
// 挂载到DOM
render(Vnode, document.body)
router.beforeEach((to, from, next) => {
Vnode.component?.exposed?.startLoading()
// 如果白名单有或者缓存有token,则可进去
if (whiteList.includes(to.path) || localStorage.getItem('token')) {
next()
} else {
next('/')
}
})
router.afterEach((to, from) => {
Vnode.component?.exposed?.endLoading()
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
上次更新: 2024/08/14, 04:14:33