在vue
项目中,vue-router
应该是必备的;我虽然使用了很多次,但其实对vue-router
还是一知半解,今天就写一篇博客来总结一下
获取 route 对象
在<script setup>
中,使用useRoute()
来获取route
对象:
const route = useRoute()
route
对象是全局单例的,在任何组件中都可以获取唯一的route
对象;拿到route
对象后,可以通过route
来获取非常多的参数和值,route
对象上的属性都是针对整个项目的浏览器url
的,在任何组件中都可以使用
route.path
获取当前url
的路径,也就是你浏览器地址栏的域名和端口后面的路径:
// 这里的浏览器 url 的路径就是指 "/lord-moon/fold-unfold"
https://gitee.com/lord-moon/fold-unfold
route.params
获取当前的路由的路径参数:
// 声明的路由对象
{
path: "/center/:id",
component: () => import("@/views/center/index.vue"),
}
/**
route.params 获取的就是 :id 的值
你可以声明多个 param,route.params 的返回值就是一个数组
*/
route.matched
获取当前所有匹配到的路由:
route.matched
会将匹配到的多层级的路由做一个扁平化,并返回一个扁平化后的数组,在实现导航面包屑功能的时候,可以使用这个API
,然后直接循环渲染route.matched
返回的数组就可以了
获取 router 对象
在<script setup>
中,使用useRouter()
来获取route
对象:
const router = useRouter()
router
对象使用得最多的就是replace
、push
、go
这三个导航方法了,还可以带上参数使用,具体请参考官方文档:编程式导航 | Vue Router (vuejs.org)
使用路由守卫
这里只讲用得最多的全局路由守卫router.beforeEach
;首先要讲清楚一些情况:
beforeEach
的第三个参数是可选的next
,但是在vue-router
的最新版本中,已经不建议使用了,所以我们在beforeEach
中就默认不再使用next
参数了官方文档对
beforeEach
的默认说明是不作任何处理的话,就会默认放行本次路由导航;所以我们在路由守卫中仅针对我们需要验证或拦截的情况作处理即可在路由守卫中
return
某个路由进行导航会再次触发路由守卫
使用 addRoute 动态添加路由
在一些 b 端项目中,我们常常会做一些角色权限验证,这时候就可能需要为不同的角色动态地展示路由
那么我们在什么时候使用addRoute
是正确的呢?如果我们在登录后使用addRoute
的话,你刷新页面之后就会空白了,因为你的routes
数组又重置为原本最初的样子了
所以我们应该统一地做addRoute
操作,那么最佳的选择就是在路由守卫beforeEach
中来动态地添加路由了:
router.beforeEach(async (to) => {
const isLogin = await checkoutLogin()
if(isLogin) router.addRoute(<路由名称>, <路由对象>)
})
但是这样你还是会发现导航到的页面还是空白的,因为你是在路由守卫里面addRoute
的,所以此时你的router
对象还没有你添加的路由,你要等添加了之后,再重定向触发一次导航守卫才可以:
router.beforeEach(async (to) => {
const isLogin = await checkoutLogin()
if(isLogin) {
router.addRoute(<路由名称>, <路由对象>)
// 重定向重新触发路由守卫
return to.path
}
})
但是这样子还不够完善,因为你导航每次都会触发路由守卫,会多次添加动态路由,所以我们需要用一个标记来判断是否是第一次添加,后续就不再添加动态路由了:
const flag = true
router.beforeEach(async (to) => {
const isLogin = await checkoutLogin()
// 使用标记判断,仅在首次的时候添加
if(flag && isLogin) {
router.addRoute(<路由名称>, <路由对象>)
// 重定向重新触发路由守卫
return to.path
}
})
这样子其实就差不多了,但还有需要注意的一点:动态地addRoute
一般需要后端返回不同角色的路由表,然后我们再添加
如果前后端不是这样设计的话,那么我建议前端直接将所有路由写为静态的,然后统一在beforeEach
中拦截即可,然后让后端接口做个权限校验就好了;因为如果不是后端动态返回的话,那么当角色多的时候,就不好维护了