​ Vue前端中的路由是多组映射关系(key-value),其中key是路径,value是组件,这些映射关系需要路由器(router)来进行管理。

​ 我们可以通过Vue Router设定访问路径,并将路径和组件映射起来,实现局部刷新界面,不需要向服务器发送请求就能切换页面


基本配置

​ 注意:vue-router@4版本对应vue3,vue-router@2版本对应vue2,千万不要弄错

main.js

​ 在main.js中引入并使用插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import App from './App.vue'
import Vue from 'vue'
import store from './store'
+ import VueRouter from 'vue-router'
+ import router from './router'
Vue.config.productionTip = false
+ Vue.use(VueRouter)
new Vue({
el: "#app",
render: h => h(App),
store,
+ router,
beforeCreate() {
Vue.prototype.$bus = this
},
})

./router/index.js

​ 在src文件夹下创建一个router文件夹,然后在其中创建index.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 该文件是专门用于创建整个应用的路由器

// 第一步引入插件(本质是一个构造函数)
import VueRouter from 'vue-router'

// 引入一下用到的组件
import TodoList from '../components/TodoList'

// 第二步创建router实例对象并暴露
const router = new VueRouter({
routes: [{
// path是路径
path: "/TodoList",
//跳转的组件
component: TodoList
}, ]
})

export default router
// 然后去main.js中引入router实例

路由的使用

router-link与router-viewer

由路由管理的地方 a标签转换成 router-link 标签 href=”相对路径” 变成 to=”路由路径”

要显示组件的地方需要用到router-view占位当点击时显示About组件中的内容时就会替换掉**router-view

通常由路由管理的组件单独放在pages文件夹下,不需要在App组件中引入和注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<template>
<div>
<div class="row">
<Banner></Banner>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- a标签在路由器中被router-link取代 -->
<!-- 使用路由提供的标签 点击跳转到/about路径 显示哪个组件在路由中配置好-->
<!-- active-class 点击时激活类名 -->
<router-link class="list-group-item"
active-class="active"
to="/about">About</router-link>
<router-link class="list-group-item"
active-class="active"
to="/home">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 这里存放由路由分配 这里放显示的组件类似于slot-->
<!-- 显示的组件会替换掉router-view -->
<router-view></router-view>
</div>
</div>
</div>
</div>
</div>
</template>

<script>
// 自己引入的组件 由路由管理的组件成为路由组件,通常放在pages文件夹下面
// 和普通的组件分开 而且不需要引入和注册
import Banner from "./components/Banner";
export default {
name: "App",
// 组测组件
components: { Banner },
};
</script>

<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 该文件是专门用于创建整个应用的路由器

// 第一步引入插件(本质是一个构造函数)
import VueRouter from 'vue-router'

// 引入要用到的组件
import About from '../pages/About'
import Home from '../pages/Home'

// 第二步创建router实例对象并暴露
export default new VueRouter({
routes: [
{

// 当路径跳转到/about时显示About组件
path: "/about",
component: About
},
{
path: "/home",
component: Home
}
]
})
// 然后去main.js中引入router实例

多级路由

​ 多级路由用到了children属性,routes中的属性成为一级路由,一级路由中children属性中的路由成为二级路由,以此类推。

​ 在一级路由中路径要写”/“ 二级路由和多级路由中的路径不写”/“

​ 跳转多级路由时,to=”路由路径” 要写全!从一级路由开始写!(如: to=”/home/news”)

可以给路由配置name属性,传递参数的时候会用到,添加name属性后跳转就不用写全路径,可以直接写路由的name (:to=”{name:’msg’}”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
routes:[
{
path:'/about',
component:About,
},
{
path:'/home',
component:Home,
children:[ //通过children配置子级路由
{
name:'news'
path:'news', //此处一定不要写:/news
component:News
},
{
name:'message'
path:'message',//此处一定不要写:/message
component:Message,
children: [
{
name:'msg'
path: 'msgdata',
component: Msgdata,
}
]
}
]

路由的传参

query传参

写法一

1
2
<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link> 

写法二

1
2
3
4
5
6
7
8
9
10
11
<!-- 跳转并携带query参数,to的对象写法 -->
<!-- name:'detail' 可以写路由的name 也可以直接写路径 -->
<router-link
:to="{
path:'/home/message/detail',
query:{
id:666,
title:'你好'
}
}"
>跳转</router-link>

组件接收数据

使用$route.query

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div>
<h3>信息编号:{{ $route.query.id }}</h3>
<h3>信息标题:{{ $route.query.title }}</h3>
</div>
</template>

<script>
export default {
name: "Msgdata",
};
</script>

<style>
</style>

当有多个需要传递的参数时,也可以在路由设置./router/index.js中使用props进行获取,然后再传递到组件中

1
2
3
4
5
6
7
8
9
//children属性下
{
path: 'msgdata',
component: Msgdata,
//在这里接收一下传来的参数,然后包装一下再传给组件
props($route){
return {id:$route.query.id, title:$route.query.title}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<div>
<h3>信息编号:{{ id }}</h3>
<h3>信息标题:{{ title }}</h3>
</div>
</template>

<script>
//组件接收
export default {
name: "Msgdata",
props: ["id", "title"],
};
</script>

<style>
</style>

params传参

路由设置

​ 在路由设置中给想使用params传参定义path属性

1
2
3
4
5
6
7
8
9
//children属性下
{
name: 'shownews'
//给需要传递的数据配置占位符
path: 'shownews/:id/:name',
component: ShowNews,
// props的第二种写法 props为布尔值,会接收所有params参数 以props的形式传递给Detail组件
props:true
}

直接路径传参

to加上冒号变成:to ,并将路径写成模板字符串,然后用${}配合模板字符串。

1
2
3
 <router-link :to="`/home/news/shownews/${n.id}/${n.name}`">
{{ n.name }}
</router-link>

写成对象形式

如果是写成对象形式的话,就不需要再路由设置中配置path属性了。

1
2
3
4
5
6
7
8
9
10
11
12
<router-link
:to="{
// 用params传递参数时用到他的对象写法中不可使用 path:'路径'
name: 'shownews',
params: {
id: n.id,
name: n.name,
},
}"
>
{{ n.name }}
</router-link>

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<ul>
<!-- query里面写数据 -->
<li>编号{{ id }}</li>
<li>姓名{{ name }}</li>
</ul>
</template>

<script>
export default {
name: "ShowNews",
props: ["id", "title"],
};
</script>

replace属性

** 不留下操作记录**
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

1. 作用:控制路由跳转时操作浏览器历史记录的模式
2. 浏览器的历史记录有两种写入方式:分别为```push```和```replace```,```push```是追加历史记录,```replace```是替换当前记录。路由跳转时候默认为```push```
3. 如何开启```replace```模式:```<router-link replace .......>News</router-link>```

---

# 编程式路由导航

​ 不借助```<router-link>``` 实现路由跳转,让路由跳转可以更灵活,其他标签也可以通过js函数实现路由跳转。

```javascript
//$router的两个API
//push:跳转并且有操作记录
this.$router.push({
name:'xiangqing',
params:{
id: xxx,
title: xxx
}
})
//replace:跳转没有操作记录
this.$router.push({
name:'xiangqing',
params:{
id: xxx,
title: xxx
}
})
this.$router.forward() //前进
this.$router.back() //后退
this.$router.go() //可前进也可后退

缓存路由组件

让不展示的路由组件保持挂载,不被销毁

其中组件如果有多个需要缓存的话,可以写成数组:"['组件1','组件2','组件']"

如果不配置include属性,则缓存所有用到的组件

1
2
3
<keep-alive include="要缓存的组件名">
<router-view></router-view>
</keep-alive>

activated和deactivated

路由组件独有的两个新的生命周期钩子,与mounted、beforeDestroy等同级别

配置在需要用到的组件内,其中:

1)activated路由组件被激活时触发。

2)deactivated路由组件失活时触发。


路由守卫

作用:对路由进行权限管理,必须符合条件才能访问

全局守卫

​ 在所有的路由发生前都执行,有三个参数to:去哪个路径,from:从哪个路径里来,next:是个函数调用的时候next()放行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 配置在实例对象外 初始化时调用,每次发生路由变化前调用
router.beforeEach((to,from,next)=>{
console.log('beforeEach',to,from)
if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
if(localStorage.getItem('school') === 'atguigu'){ //权限控制的具体规则
next() //放行
}else{
alert('暂无权限查看')
// next({name:'guanyu'})
}
}else{
next() //放行
}
})

//全局后置守卫:初始化时执行、每次路由切换后执行
router.afterEach((to,from)=>{
console.log('afterEach',to,from)
if(to.meta.title){
document.title = to.meta.title //修改网页的title
}else{
document.title = 'vue_test'
}
})

独享守卫

​ 放在需要进行权限设置的路由里面,参数语法和全局一样 当访问这个路径前才执行beforeEnter()

1
2
3
4
5
6
7
8
9
10
11
12
13
beforeEnter(to,from,next){
console.log('beforeEnter',to,from)
if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
if(localStorage.getItem('school') === 'atguigu'){
next()
}else{
alert('暂无权限查看')
// next({name:'guanyu'})
}
}else{
next()
}
}

组件守卫

放在组件里,和methods,components同级别 ,

必须是通过路由规则进入该组件才可以调用

beforeRouteEnter(),beforeRouteLeave()

1
2
3
4
5
6
   //进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {
},
//离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {
}

附录

参考文章:

道貌岸然304——Vue中的路由