vue-router
vue的一个插件库,专门用来实现SPA应用(单页面应用)。
路由
- 一个路由就是一组映射关系(key和value)
- key为路径,value可能为组件(前端路由)或函数(后端路由),前端根据路径展示不同组件
- 多个路由需要路由器管理
路由的基本使用
- 安装vue-router
npm install vue-router@3 // vue2
- 使用插件
import VueRouter from 'vue-router'
Vue.use(VueRouter)
- 配置router
// 引入vue-router
import VueRouter from 'vue-router'
// 引入组件
import component1 from '../components/component1'
import component2 from '../components/component2'
// 创建并暴露router
export default new VueRouter({
// 实例对象下的路由规则
routes = [
{
path: '/first',
component: component1
},
{
path: '/second',
component: component2
}
]
})
- 路由切换
// active-class配置点击时的高亮样式 to为点击时的匹配路径
<router-link active-classs="active" to="/first">first</router-link>
<router-link active-classs="active" to="/second">second</router-link>
- 指定组件展示位置
<router-view></router-view>
注意点
- 路由组件通常存放在
pages文件夹中,一般组件通常存放在components文件夹 - 通过切换,隐藏的路由组件默认被销毁,点击时会再次挂载
- 每个组件都有自己的
$route属性,里面存储着自己的路由信息 - 整个应用只有一个router,可以通过组件的
$router属性获取到,每个组件的$router属性相同
嵌套(多级)路由
- 配置路由规则,通过
children配置子级路由
routes = [
{
path: '/first',
component: component1
},
{
path: '/second',
component: component2,
children: [
{
path: 'page1', // 不能写成'/page1'
component: pageFirst
},
{
path: 'page2', // 不能写成'/page2'
component: pageSecond
}
]
}
]
- 路由跳转
<router-link active-classs="active" to="/second/page1">组件A</router-link>
<router-link active-classs="active" to="/second/page2">组件B</router-link>
路由query参数
- 传递参数:跳转并携带参数
// 字符串写法
<router-link :to="/second/page1?id=666&name=hello`">组件A</router-link>
<router-link :to="`/second/page1?id=${xxx}&name=${xxx}`">组件A</router-link>
// 对象写法
<router-link
:to={
path:/second/page1
query:{
id: xxx,
name: xxx
}
}
>组件A
</router-link>
2.接收参数:query参数可以从组件$route属性中的query得到
$route.query.id
$route.query.name
命名路由
- 给路由配置
name属性
routes: [
{
path: '/demo',
component: demo,
children: [
{
path: 'test',
component: test,
children: [
{
name:ceshi,
path: 'ceshi',
component: ceshi
}
]
}
]
}
]
- 简化to的写法
// 简化前
<router-link to="/demo/test/ceshi"></router-link>
// 简化后:直接通过名字跳转
<router-link :to="{name: 'ceshi'}"></router-link>
// 结合传参
<router-link
:to="{
name: 'ceshi',
query: {
id:666,
title: 'hello'
}
}"
></router-link>
路由params参数
- 在配置路由时,必须声明接收
params参数
routes: [
{
path: '/demo',
component: demo,
children: [
{
path: 'test',
component: test,
children: [
{
name:ceshi,
path: 'ceshi/:id/:title', // 使用占位符声明接收params参数
component: ceshi
}
]
}
]
}
]
- 传递参数
// 字符串写法
<router-link to="/demo/test/ceshi/666/你好"></router-link>
// 对象写法
<router-link
:to="{
// 传递params时,不能使用path属性,必须用name跳转
name: 'ceshi',
params: {
id:666,
title: 'hello'
}
}"
></router-link>
- 接收参数:params参数可以从组件
$route属性中的params得到
$route.query.id
$route.query.name
路由的props
作用可以让路由组件更方便的接收到参数
{
name: 'ceshi',
path: 'ceshi/:id'
component: ceshi,
// 对象写法
props: {id: 666}
// 布尔值写法,当props为true,则把路由收到的所有params参数传给组件,同时组件用props接收
props: true
// 函数写法,接收组件的$route为参数,返回值中每一组key-value都会通过props传递给组件
props($route){
return {id: $route.query.id}
}
}
<router-link>的push和replace属性
- 浏览器的历史记录有两种写入方式:
push(追加记录)和replace(替换当前记录)。作用:控制路由跳转时操作浏览器历史记录的模式。路由跳转时默认是push模式。
上图中/about和/home均为push方式,/new为replace方式,从/new后退到上一个路由则为/about。
- 开启
replace模式
<router-link replace></router-link>
// 等同于
<router-link :replace="true"></router-link>
编程式路由导航
- 不借助
<router-link>,使用API实现路由跳转
// $router的两个API
// 跳转并保留上一个路由
this.$router.push({
name: 'detail',
params: {
id: 666,
title: 'hello'
}
})
// 跳转并替换上一个路由
this.$router.replace({
name: 'detail',
params: {
id: 666,
title: 'hello'
}
})
this.$router.forward() // 前进
this.$router.back() // 后退
this.$router.go() // 可前进也可后退,参数为步数
缓存路由组件
<keep-alive>让不展示的组件保持挂载,不销毁。
// 没有include则默认缓存所有在<router-view>展示的组件
// 缓存一个路由组件
<keep-alive include="组件名">
<router-view></router-view>
</keep-alive>
// 缓存多个路由组件
<keep-alive :include="[组件1, 组件2]">
<router-view></router-view>
</keep-alive>
路由组件的生命钩子
- 路由组件所独有的两个钩子,用于捕获路由组件的激活状态
activated路由组件被激活时触发,deactivated路由组件失活时触发
路由守卫
- 路由守卫对路由进行权限控制(鉴权),包括全局守卫、独享守卫和组件内守卫
- 全局守卫包括全局前置路由守卫和全局后置路由守卫
const router = new VueRouter({
routes = [
{
name: 'xxx',
path: '',
meta: {isAuth: true}
}
]
})
// 全局前置路由守卫...
// 全局后置路由守卫...
export default router
// 全局前置守卫:初始化时执行,每次路由切换前执行
// to为目的路由,from为源路由
router.beforeEach((to, from, next) => {
if (to.meta.isAuth){ // 判断当前路由是否需要权限控制(鉴权)
if (localStore.getItem('xxx') === 'xxx'){ // 权限控制的具体规则
next() // 放行
}else {
alert('暂无权限')
}
}else {
next() // 放行
}
})
// 全局后置守卫:初始化时执行,每次路由切换后执行
router.afterEach((to, from) => {
if (to.meta.title) {
document.title = to.meta.title // 修改网页title
}else {
document.title = 'xxx'
}
})
- 独享路由守卫为某个路由所独享的,只有前置独享守卫
{
// ...
beforeEnter((to, from, next) => {})
}
- 组件内守卫必须通过路由规则切换组件才能触发
// 进入守卫:进入该组件时被调用
beforeRouteEnter(to, from, next){}
// 离开守卫:离开该组件时被调用
beforeRouteLeave(to, from, next){}
路由器的两种工作模式
路由器的工作模式包括hash和history。 hash值是url中#及其后面的内容,hash值不会包含在HTTP请求中,即不会带给服务器。
hash模式
- 地址中永远带着
#号 - 若以后将地址通过第三方手机app分享,当app校验严格时,带
#的地址会被标记为不合法 - 兼容性较好
history模式
- 地址不带
#号 - 兼容性较hash模式略差
- 应用部署上线后需要后端人员支持,解决页面刷新呈现404的问题