当前位置:首页 > 编程笔记 > 正文
已解决

vue-router学习(三) --- 导航守卫

来自网友在路上 159859提问 提问时间:2023-11-01 21:55:21阅读次数: 59

最佳答案 问答题库598位专家为你答疑解惑

文章目录

  • 全局导航守卫
  • 路由独享导航守卫
  • 组件内的守卫
  • 完整的导航解析流程
  • loadingBar 案例

  1. 全局导航守卫
    • beforeEach
    • beforeResolve
    • afterEach
  2. 路由导航守卫
    • beforeEnter
  3. 组件导航守卫
    • beforeRouteEnter
    • beforeRouteUpdate
    • beforeRouteLeave

全局导航守卫

当一个导航触发时,全局前置守卫按照创建顺序调用。
守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。参数说明:
to: Route, 即将要进入的目标 路由对象;
from: Route,当前导航正要离开的路由;
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。全局前置守卫
router.beforeEach((to,from,next)=>{if(xxxxx){next('/login')}else{next()}
})全局解析守卫
注意:解析守卫刚好会在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用
router.beforeResolve(()=>{})全局后置钩子
守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身
它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用
router.afterEach((to, from) => {sendToAnalytics(to.fullPath)
})

案例

const whileList = ['/']router.beforeEach((to, from, next) => {let token = localStorage.getItem('token')//白名单 有值 或者登陆过存储了token信息可以跳转 否则就去登录页面if (whileList.includes(to.path) || token) {next()} else {next({path:'/'})}
})

路由独享导航守卫

const routes = [{path: '/users/:id',component: UserDetails,beforeEnter: (to, from) => {// reject the navigationreturn false},},
]

beforeEnter 守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发。例如,从 /users/2 进入到 /users/3 或者从 /users/2#info 进入到 /users/2#projects。它们只有在 从一个不同的 路由导航时,才会被触发

beforeEnter作用的是目标路由对象

组件内的守卫

const UserDetails = {template: `...`,beforeRouteEnter(to, from) {在渲染该组件的对应路由被验证前调用不能获取组件实例 `this` !因为当守卫执行时,组件实例还没被创建!},beforeRouteUpdate(to, from) {在当前路由改变,但是该组件被复用时调用举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1``/users/2` 之间跳转的时候,由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`},beforeRouteLeave(to, from) {在导航离开渲染该组件的对应路由时调用与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`},
}

完整的导航解析流程

  1. 导航被触发
  2. 在之前失活的组件触发beforeRouterLeave
  3. 调用全局前置守卫beforeEach
  4. 如果是重用的组件/user/:id,调用beforeRouterUpdate更新组件
  5. 然后执行路由守卫beforeEnter
  6. 解析异步路由组件
  7. 然后执行组件内的beforeRouterEnter
  8. 然后会调用全局解析守卫beforeResolve
  9. 这时候导航已经被确认了
  10. 调用全局后置钩子afterEach
  11. 触发 DOM 更新
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

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 = 1timer.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 + '%'})}, 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>
main.ts
import loadingBar from './components/loadingBar.vue'
const Vnode = createVNode(loadingBar)
render(Vnode, document.body)
console.log(Vnode);router.beforeEach((to, from, next) => {Vnode.component?.exposed?.startLoading()
})router.afterEach((to, from) => {Vnode.component?.exposed?.endLoading()
})
查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"vue-router学习(三) --- 导航守卫":http://eshow365.cn/6-29636-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!