Vue Router
本文将介绍 Vue Router,Vue 官网的路由管理器。
一、什么是 Vue Router?
1. 什么是路由?
路由是通过互联的网络把信息从源地址传输到目的地址的活动
路由器提供了两种机制:
- 路由:决定数据包从来源到目的地的路径
- 传送:将输入端的数据转移到合适的输出端
2. 什么是前端路由?
具体请看:
3. 如何修改 URL 并使页面不刷新?
(1) hash
URL 的 hash ,即页面的锚点,代表网页中的一个位置。锚点是 URL 中 #
之后的部分,例如:
1 |
|
URL 中的 hash 有以下几点特性:
- hash 不包括在 HTTP 请求中
- 改变 hash 并不会触发页面重载
- 改变 hash 会改变浏览器的访问记录
(2) history
HTML5 提供 history 接口,通过 state 的形式修改 URL,其实现函数是 pushState 和 replaceState。
修改 URL
1 |
|
其中,
- state 是对象,可以为空
- title 是字符串,可以为空
- url 用于设置 URL 地址
前进后退:
1 |
|
二、基本使用
1. 安装
(1) 法 1
1 |
|
(2) 法 2
通过 Vue CLI 创建项目,并选择 Vue Router 。
2. 配置
router.js
1 |
|
main.js
1 |
|
3. 路由映射表
router.js
1 |
|
修改默认路径:
增加一个空路径的映射,并将它重定向至首页。
1
2
3
4
5
6
7
8
9
10
routes: [
{
path: '',
redirect: '/home'
},
{
path: '/home',
component: Home
}
]
4. router-view
为了在跳转路径后显示对应的组件,应该在 App.vue 的 HTML 模板中设置 router-view ,用于渲染路径所匹配的组件。
在跳转路径后,router-view 将会动态渲染为对应的组件,并且切换时仅有 router-view 会刷新,而其它内容不会改变。
1 |
|
5. 修改路由模式
可以在 Vue Router 的 hash 模式和 history 模式之间切换,通过修改 router/index.js 实现。
router.js
1 |
|
三、跳转路径
1. router-link
1 |
|
router-link 用于页面跳转,会被默认渲染为 a 标签
tag='标签名'
,用于指示超链接的样式replace
,用于将链接跳转设为 replaceState 模式(即没有历史记录,不可以前进后退)actice-class=active
,用于修改标签为 active 状态时的类名默认情况下,Vue Router 会为处于 active 状态的 router-link 标签增设一个类名,默认为 router-link-active 。
也可以通过设置 router/index.js ,从而将修改所有 active 状态的 router-link 标签的新增类名。
2. 手动跳转路径
不要直接使用 hash 或 history 直接修改路径,而是应该让 Vue Router 帮忙做。
在 Vue 实例内部,通过
$router
访问路由实例。
1 |
|
四、嵌套路由
1. 什么是嵌套路由
在实际的应用场景中,我们可能希望通过 /home/news
访问 home 下的新闻,通过 /home/message
访问 home 下的信息。
使用嵌套路由,便可以很好地实现这一效果。
2. 嵌套路由的实现
Home.vue
- 为两个子组件设置链接
- 增加 router-view ,以便渲染为子组件
1 |
|
router.js
引入两个子组件
在父路由的 children 中填入两个子组件
path 不应该加
/
1 |
|
五、动态路径
1. 什么是动态路径?
在某些情况下,页面的路径并不是固定的。
比如一般用户界面对应的路径:
1 |
|
2. 解决方法
(1) router-link
router-link 应该能够指定动态生成的路径,因此正确的做法是:
- 实现获取动态路径中的动态参数
- 通过计算属性等方法拼接动态路径
- 通过 v-bind 将动态路径绑定至 router-link 的属性中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<template>
<div id="app">
<router-link :to="userurl">{{userid}}</router-link>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return {
userid: 'zhangshan',
}
},
computed: {
userurl: function() {
return '/User/'+this.userid;
}
}
}
</script>
(2) 路由映射表
对于路径中的 “动态参数”,应该使用 :参数名
来占位。
1 |
|
设置后,类似 /.../XXX/...
的路径都将被匹配,映射到相同的组件。
匹配到路由后,参数将会被设置到 this.$route.params 之上,可以在组件中调用这一参数。
(3) 获取动态参数
可以通过 this.$route.params.参数名
来获取当前路径下的动态参数。
假设动态路径在路由映射表中配置如下:
1
2
3
4
5
routes: [
{
path: '/users/:id',
}
]当前路径为:
1
/users/1001
则可以通过
this.$route.params.id
获得当前的 id 动态参数,其值为 1001 。
六、路由懒加载
1. 什么是路由懒加载?
单页面富应用只有一张 HTML 页面,在用户与应用程序交互时动态更新页面。
这种方式有许多优点,但由于所有的资源都放在一起,初次加载时耗时会较长。
因此,有时需要将不同路由对应的组件分割成不同的代码块,当路由被访问时才加载对应组件,这便是路由懒加载。
2. 路由懒加载的实现
不再直接 import 组件
通过异步函数来 import 组件
1
const Foo = () => import('组件路径')
非懒加载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(Router)
const routes = [
{
path: '/home',
component: Home
}
]
const router = new Router({
routes
})
export default router懒加载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue'
import Router from 'vue-router'
const Home = () => import('../views/Home.vue')
Vue.use(Router)
const routes = [
{
path: '/home',
component: Home
}
]
const router = new Router({
routes
})
export default router
七、参数传递
1. params
路由映射表配置:将路由中的路径设为
/页面/:参数名
传递方式:
/页面/参数
传递后形成的路径:
路径/参数
获取参数:
this.$route.params.参数名
2. query
路由映射表配置:路由中的路径无需额外配置
传递方式:
1
2
3
4
5
6
7<router-link :to="{
path: '/页面',
query: {
name: 'xiaozhang',
age: 18,
}
}"></router>- 通过 v-bind 绑定属性,以便于解析对象(而不是将它当作字符串)
- 在 path 指定跳转的页面
- 在 query 中填入需要传递的内容
传递后形成的路径:
获取参数:
this.$route.query.参数名
八、导航守卫
1. 什么是导航守卫?
Vue Router 提供的导航守卫主要用来监听路由的进入和离开,并提供了 beforeEach 和 afterEach 等方法,可以在路由跳转时执行相应的操作。
可以用于修改页面标题、防止用户直接通过修改 URL 访问特定页面等场景。
2. 全局前置守卫
1 |
|
守卫方法接收三个参数:
to:即将进入的目标路由对象
from:即将离开的路由对象
next():一个方法,应该保证该方法在任何导航守卫中都被严格调用一次
next()
代表放行next('/路径')
代表跳转至指定路径next({path: '/路径', ···})
代表跳转至指定路径,可以在对象中设置诸如replace: true
、name: 'home'
等选项
next(...)
将会中断当前的导航,并进入新的导航,因此新的导航也会被导航守卫拦截。
示例-在跳转页面时修改标题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Vue.use(Router)
const router = new Router({
mode: 'history',
routes: [
{
name: '你好',
path: '/helloworld',
component: HelloWorld
}
]
})
router.beforeEach((to, from, next) => {
next()
document.title = to.name
})
export default router
2. 全局解析守卫
在 2.5.0+ 你可以用
router.beforeResolve
注册一个全局守卫。这和
router.beforeEach
类似,区别是:在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
3.全局后置钩子
和守卫不同的是,它不会接受 next
函数也不会改变导航本身。
因为页面已经跳转完了
1 |
|
4. 路由独享守卫
可以为某一个路由单独配置守卫。
1 |
|
5. 组件内的守卫
1 |
|
6. 完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
九、keep-alive
1. 什么是 keep-alive?
keep-alive 是 Vue 内置的组件,可以使被包含的组件保留状态、避免重新渲染。
如果将 router-view 放置在 keep-alive 之中,则所有路径匹配到的视图组件都将被缓存,而不会被销毁。
1 |
|
2. activated() 和 deactivated()
被 keep-alive 包裹的组件可以调用 activated() 和 deactivated() 这两个生命周期钩子函数
activated():组件进入活跃状态时执行
deactivated():组件离开活跃状态时执行
1 |
|
3. include 和 exclude
keep-alive 有两个重要属性:
- include:字符串或正则表达式,只有匹配的组件才会被缓存
- exclude:字符串或正则表达式,只有不匹配的组件才会被缓存
1 |
|