概念:路径和组件(页面)的映射(对应)关系
应用场景:实现页面的切换
特点(SPA):
(1)整个应用只有一个入口的网页,是区别MPA(多页面应用)
(2)局部刷新,用户体验好
(3)数据传输方便,提高开发效率
(4)首次加载速度慢,不利于SEO
嵌套(多级)路由
1.配置路由规则,使用children 配置项:
2.页面中router-link to:"/path" (path 要写完整路径)
路由传参
1.传递参数------query
//跳转并携带query 参数,to的字符串写法
<router-link :to="/home/message/detail?id=666&title=你好"> 跳转</router-link>
//跳转并携带query参数,to的对象写法
<router-link :to="{
path:"/home/message/detail",
query:{
id:m.id,
title:m.title
}
}">
//接收参数
$route.query.id
2.传递参数-------params
//跳转并携带 params 参数 ,to的字符串写法
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
//跳转并携带 params 参数,to的对象写法
<router-link :to="{
name:'xiaoming',
params:{
id:666,
title:'你好'
}
}">跳转</router-link>
//接收参数
$router.params.id
$router.params.title
注意: 路由携带 params 参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置
路由的props配置
作用:让路由组件更方便的收到参数
{
name:'xaingqing',
path:"/detail/:id",
component:Detail,
//props的第一种写法: 值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
// props:{a:1,b:'hello'}
//props的第二种写法: 值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props形式传给Detail组件 (只接受到params参数)
//props:true
//props的第三种写法:值为函数
props($route){
return{id:$route.query.id,title:$route.query.title}
}
}
//<router-link>的replace属性
// 1.作用: 控制路由跳转时的操作浏览器历史浏览记录的模式
// 2.浏览器的历史记录有两种写入方式:分别为 push 和 replace,push是追加历史记录,replace是替换当前记录.路由跳转时默认为push
// 3.如何开启replace模式:<router-link replace ....>News<router-link>
编程式路由导航
作用:不借助 router-link实现路由跳转,让路由跳转更加灵活
//$router的两个API
this.$router.push({
name:'xaingqing',
params:{
id:111,
title:xxx,
}
})
this.$router.replace({
name:'xaingqing',
params:{
id:111,
title:xxx,
}
})
this.$router.forward() //前进
this.$router.back() //后退
this.$router.go(1) //可前进也可后退,看传的参数是正还是负
缓存路由组件
作用:让不展示的路由组件保持挂载,不被销毁
//$router的两个API
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
两个新的声明周期钩子
作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态
路由的配置项
hidden: true //当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1
alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面;只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面; 若你想不管路由下面的 children 声明的个数都显示你的根路由,你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由
redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数
roles: ['admin', 'common'] // 访问路由的角色权限
permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限
meta : {
noCache: true, // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
title: 'title', // 设置该路由在侧边栏和面包屑中展示的名字
icon: 'svg-name', // 设置该路由的图标,对应路径src/assets/icons/svg
breadcrumb: false, // 如果设置为false,则不会在breadcrumb面包屑中显示
activeMenu: '/system/user', // 当路由设置了该属性,则会高亮相对应的侧边栏。
}
全局前置路由守卫
概念:初始化的时候被调用,每次切换路由之前被调用 (可处理鉴权问题 ---判断用户是否携带token)
const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
router.beforeEach((to, from, next) => {
// to:从当前路由去哪个路由页面
// from:从哪个路由页面来到当前路由页面
// next:放行
NProgress.start()
if (getToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => {
store.dispatch('GenerateRoutes').then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
} else {
next()
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
全局后置路由守卫
概念:初始化的时候调用,每次路由一切换之后被调用
router.afterEach(((to, from, next) => {
NProgress.done()
})
独享守卫
beforeEnter(to,from,next){
//可判断当前路由是否需要进行权限控制
}
组件内守卫
//进入守卫: 通过路由规则,进入该组件时被调用
beforeRouteEnter(to,from,next){
},
//离开守卫: 通过路由规则,离开该组件时被调用
beforeRouteLeave(to,from,next){
}
END