一、router-link
1、不带参数
<router-link :to="{name:'home'}">
<router-link :to="{path:'/home'}">
2、带参数
<router-link :to="{name:'home', params: {id:1}}">
// 路由配置 path: "/home/:id" 或者 path: "/home:id"
url的参数不可见,刷新后参数会消失
<router-link :to="{name:'home', query: {id:1}}">
// 路由可不配置
url带的参数是可见的,刷新后参数不会消失
二、root.$router.push() (函数里面调用)
1、不带参数
this.$router.push('/home')
this.$router.push({name:'home'}) this.$router.push({path:'/home'})
2、query传参
this.$router.push({name:'home',query: {id:'1'}}) this.$router.push({path:'/home',query: {id:'1'}})
url带的参数是可见的,刷新后参数不会消失
3、params传参
this.$router.push({name:'home',params: {id:'1'}})
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,,刷新页面参数会消失
// 配置path,刷新页面id会保留
4、query和params区别
query跳转配合路由 path 属性,传参为明文,url上参数可见,刷新后参数不会消失
Params路转配合路由 name 属性,传参为密文,url上参数不可能,刷新后参数会消失
三、Router跳转、接收参数
query参数路转
root.$router.push({ path:'/select', //跳转的路径 query:{ id:this.id , } })
参数接收:root.$route.query.xxxxxxx
Params参数路转
root.$router.push({ name:‘Select', //跳转的路径 params:{ id:this.id , } })
参数接收:root.$route.params.xxxxxxx
$router 和$route 的区别:
router为VueRouter的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象.
route相当于当前正在跳转的路由对象,可以从里面获取name,path,params,query等.
四、路由守卫
1.router.beforeEach((to,from,next))路由跳前:
ext: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next() 执行了to里面的路由对象
进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false):
中断当前的导航。
如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/') 或者 next({ path: '/' }):
跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在 router-link 的 toprop 或 router.push 中的选项。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
确保要调用 next 方法,否则钩子就不会被 resolved。
2.作用(权限验证,动态路由)
router.beforeEach((to, from, next) => { NProgress.start() // 开始 progress bar if (getToken()) { // 判断token /* has token*/ if (to.path === '/login') { next({ path: '/' }) NProgress.done(); } else { if (store.getters['user/roles'].length === 0) { // 判断当前用户是否已拉取完user_info信息 store.dispatch('user/GetUserInfo').then(res => { // 拉取user_info const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop'] store.dispatch('permission/GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表 router.addRoutes(store.getters["permission/addRouters"]) // 动态添加可访问路由表 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record }) }).catch((err) => { store.dispatch('FedLogOut').then(() => { Message.error(err) next({ path: '/' }) }) }) } else { next(); }
} } else { /* 无 token */ if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入 next() } else { next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 NProgress.done() // 如果是登入页面,要手动处理 } } }) router.afterEach(() => { NProgress.done() // finish progress bar })
五、动态路由
将路由分为constantRouterMap和asyncRouterMap组,在路由守卫中,根据用户的权限,去匹配asyncRouterMap组中的路由加载到router中去:
if (store.getters['user/roles'].length === 0) { // 判断当前用户是否已拉取完user_info信息 store.dispatch('user/GetUserInfo').then(res => { // 拉取user_info const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop'] store.dispatch('permission/GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表 router.addRoutes(store.getters["permission/addRouters"]) // 动态添加可访问路由表 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record }) }).catch((err) => { store.dispatch('FedLogOut').then(() => { Message.error(err) next({ path: '/' }) }) })
permission/GenerateRoutes方法:
import { asyncRouterMap, constantRouterMap } from "@/router"; /** * 通过meta.role判断是否与当前用户权限匹配 * @param roles * @param route */ function hasPermission(roles, route) { if (route.meta && route.meta.roles) { return roles.some((role) => route.meta.roles.includes(role)); } else { return true; } } /** * 递归过滤异步路由表,返回符合用户角色权限的路由表 * @param routes asyncRouterMap * @param roles */ function filterAsyncRouter(routes, roles) { const res = []; routes.forEach((route) => { const tmp = { ...route }; if (hasPermission(roles, tmp)) { if (tmp.children) { tmp.children = filterAsyncRouter(tmp.children, roles);
} res.push(tmp); } }); return res; } const state = { routers: constantRouterMap, addRouters: [], }; const getters = { permission_routers: (state) => state.routers, addRouters: (state) => state.addRouters, }; const mutations = { SET_ROUTERS: (state, routers) => { state.addRouters = routers;
state.routers = constantRouterMap.concat(routers); console.log(state.routers); }, }; const actions = { GenerateRoutes({ commit }, data) {
return new Promise((resolve) => { const { roles } = data; let accessedRouters; if (roles.includes("admin")) { accessedRouters = asyncRouterMap; } else { accessedRouters = filterAsyncRouter(asyncRouterMap, roles); } commit("SET_ROUTERS", accessedRouters); resolve(); }); }, }; export default { namespaced: true,//vuex 命名空间 state, getters, mutations, actions, };