一、安装
- 方式一: 通过
JavaScript 或者 CDN 引入
https://unpkg.com/vue-router/dist/vue-router.js
npm install vue-router
注意:如果在模块化工程中使用vue,必须使用Vue.use()来明确的安装路由功能
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
vue add router
二、vue-router是什么
vue-router 是 vue 官方的路由管理器,主要用于单页面之间的路由跳转。
vue-router主要包含的功能有哪些?
- 可嵌套的路由/视图
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于 vue.js过渡系统的页面过渡效果
- 细粒度的导航控制
- 激活状态下的css class 的配置
- 支持hash模式 和 history 模式
- 自定义的滚动条行为
三、核心概念
1 - 路由实例
通过 new 一个路由对象从而得到路由实例。 当我们在项目中已经注入路由之后就可以通过this.$router 的方式访问到路由实例 通过 this.$route 访问当前路由。
const router = new VueRouter({
...
})
2 - 路由标签
router-link 组件 和 router-view 组件是路由系统的基础标签,主要用以路由跳转及视图展示。
3 - 动态路由匹配
-
使用场景 我们通常把不同模式匹配到的路由,全部映射到同一个组件上。即:不同的路由地址匹配相同的组件。 -
如何实现动态匹配 动态匹配路由:由 : 开始标记一个动态路由匹配。当成功匹配到一个路由时,动态值会作为参数被配置到 this.$route.params 中,可以在任何组件中获取到该值。 例如:我们要实现一个 从 user/Tom 跳转到 user/Join 的路由跳转,但是两个路由匹配的组件都是 UserInfo 组件。
const router = new VueRouter({
routes:[{
path:"/user/:id",
component:UserInfo
}]
})
const UserInfo = {
template:`<div>{{ this.$route.params.id }}</div>`
}
- 多段参数路由匹配
如果路由有多个参数,需要进行多段路由匹配,在动态路由配置中也是完全支持的。例如:user/:id/age/:num 可以匹配到 user/12/age/18 , 此时路由下的参数为:
this.$route.params = {
id:'12',
num:'18'
}
const UserInfo = {
watch:{
$route(to , from){
}
}
}
(2)通过路由守卫 beforeRouterUpdate 来监听路由变化
const UserInfo = {
beforeRouteUpdate(to , from , next){
}
}
如果我们想要匹配到任意路由,或以指定前缀开头的任意路由,就可以使用到通配符*
{
path:*
}
{
path:'user-*'
}
注意:在使用通配符时,要注意使用顺序,一般我们使用通配符是为了匹配404界面,所以此时通配符一定是放在最后一项的,当所有的理由匹配都没有结果时,匹配404界面;
如果我们在route中使用同一个路径匹配了多个路由,则谁先定义的谁的优先级最高。
4 - 嵌套路由
一个被渲染的视图组件 router-view 的模板里可以包含自己嵌套的视图组件 router-view ,即嵌套路由。 例如在User组件中嵌套视图:app 中对应的视图是顶层出口,在User中的视图属于嵌套出口。
<div id="app">
<router-view></router-view>
</div>
const User = {
template: `
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`
}
在定义路由的时候,使用 children 属性来配置嵌套路由。
const router = new VueRouter({
routes: [
{ path: '/user/:id',
component: User,
children: [
{
path: 'profile',
component: UserProfile
},
{
path: 'posts',
component: UserPosts
}
]
}
]
})
注意:所以使用 / 开头的嵌套都会被映射到根路径上。所以在子路径上只使用路径名即可。
以上的配置中,如果输入 user/foo ,在嵌套视图中是不会显示任何组件的,如果想在嵌套路由中设置一个默认组件,可以添加以下配置:
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: User,
children: [
{ path: '', component: UserHome },
]
}
]
})
5 - 编程式导航
我们除了使用 router-link 组件进行导航外,还可以调用 router 的实例方法进行导航,这种通过调用方法的导航形式被称为编程式导航。而使用 router-link 的方式叫声明式导航。 ?
-
常用的实例方法
- push()路由跳转
- replace()路由替换
- go()路由回退
-
push方法
- 作用: 进行路由跳转,导航到不同的url。
- 特性:通过push跳转的路由,会向history中添加一条记录,当用户点击浏览器的回退按钮时会回退到之前的url中。而我们在使用
router-link 时,在内部调用了push方法,所以调用push等同于点击了 router-link - 参数:接受一个字符串或者一个对象
router.push('home')
router.push({ path: 'home' })
router.push({ name: 'user', params: { userId: '123' }})
router.push({ path: 'register', query: { plan: 'private' }})
使用对象参数,一定要注意:如果定义了path属性,则params属性会被忽略,如果想要使用params属性,前面的值只能是name
const userId = '123'
router.push({ name: 'user', params: { userId }})
router.push({ path: `/user/${userId}` })
router.push({ path: '/user', params: { userId }})
-
replace方法
- 作用:和 push 方法类似,用于路径跳转
- 特性:不会向 history中添加新的记录,而是替换掉当前的history记录
- 参数:和 push 方法一致。
- 声明式:``
-
go方法
- 作用:路由回退。在history中回退指定的步数
- 参数:接受一个整数
router.go(1)
router.go(-1)
router.go(3)
router.go(-100)
router.go(100)
6 - 命名路由
即在定义路由的时候,给路由设置一个name属性用于标志当前路由。尤其在具有路由参数的时候。
const router = new VueRouter({
routes:[{
path:"user/:id",
name:"user",
component:User
}]
})
<router-link :to='{name:"user",params:{id:123}}'>user</router-link>
this.$router.push({
name:"user",
params:{
id:"123"
}
})
7 - 命名视图
即 给 路由视图 router-view 添加name属性。没有name属性的视图默认为 default
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
当我们想要在一个组件中同时同级的展示多个 路由视图,此时就需要使用命名视图来控制每个路由视图匹配的组件
const router = new VueRouter({
routes:[{
path:"user",
components:{
default:Foo,
a:Bar,
b:Baz
}
}]
})
8 - 重定向和别名
(1)重定向
const router = new VueRouter({
routes:[{
path:"/a",
redirect:"/b"
}]
})
const router = new VueRouter({
routes:[{
path:"/a",
redirect:{
name:"/b"
}
}]
})
const router = new VueRouter({
routes:[{
path:"/a",
redirect:to => {
}
}]
})
(2)别名
别名的含义是指给当前路由添加一个其他名称。当访问这个名称时,和访问path的效果是一样的。 例如:当访问/b时,url会保持/b ,但是路由匹配规则会匹配/a。一般用于想要简化路由或者嵌套路由时。
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
9 - 路由组件传参
一般我们获取路由中的参数会使用 $route.params.id 获取到我们需要的参数。但是$route 于目前的路由行程高度耦合,使得组件只能在特定的路由下使用。
使用 props 属性,将路由组件解耦。
- 首先,在组件中使用 props 属性接受路由参数
- 然后,在定义路由对象的时候设置当前路由的props属性为true
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true },
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
})
四、使用进阶
1 - 导航守卫
(1)什么是导航守卫
导航守卫类似于导航的一个生命周期,主要从进入导航、导航跳转、取消导航等方面进行导航守卫
(2)导航守卫的种类
- 全局前置守卫
- 全局解析守卫
- 全局后置守卫
- 路由独享守卫
- 组件内守卫
(3)全局前置守卫
const router = new VueRouter({...})
router.beforeEach( (to , from , next) => {...} )
to:Router:
from:Router:// 表示跳转来源的路由对象
next:Function:
next();不传参数表示直接进入管道中的下一个钩子,如果所有钩子都已经执行结束,则导航的状态就是confirm的状态。
next( false ):传入false表示中断路由跳转,如果url的导航改变了,则会重置到 from 对应的地址。
next( '/' ): 进入到next指定的路由对象中,支持传入一个路由对象,允许 replace、name等等路由灯箱支持的属性.
重点说明:next 函数一定要确保在任何一个导航守卫中被严格执行一次,否则钩子不会被解析或者解析报错。
(4)全局解析守卫
- 注册使用 - beforeResolve
- 调用时间:在导航被确认之前,且同时在所有组件内的守卫和异步路由组件被解析之后执行
(5)全局后置守卫
- 注册使用 - afterEach
- 调用事件:路由导航解析之后
- 用途:一般用于在路由解析成功后统一执行某些函数
(6)路由独享守卫
- 注册使用 - beforeEnter
- 用途:针对单独某个路由的前置守卫,使用方法和全局前置守卫一致,只是 类似于作用域不同
- 使用实例:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
(7)组件内守卫
直接在组件内部定义的路由守卫,被称之为组件内守卫。
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouterLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
},
beforeRouteUpdate (to, from, next) {
},
beforeRouteLeave (to, from, next) {
}
}
在 beforeRouteEnter 中我们无法获取到 this 实例,但是又想使用实例怎么办?在 beforeRouteEnter 钩子中支持给next 函数传递 实例作为参数,然后在next的回调函数中进行一些操作,
beforeRouteEnter (to, from, next) {
next(vm => {
})
}
(8)导航解析流程

2 - 路由元信息
meta 属性,我们在定义路由的时候可以使用mate 字段,meta 字段接受任意值
- 如何访问到meta字段
- 路由记录:在routes 配置中的每一个路由对象都被称之为路由记录
- $router.matched 数组:一个路由匹配到的所有路由记录都会暴露给matched数组
- 访问meta字段:
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!auth.loggedIn()) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next()
}
3 - 过渡效果
<transition>
<router-view></router-view>
</transition>
- 单个路由的过渡效果
- 单个路由的过渡效果:即针对每一个组件都有自己对对应的不同的过渡效果
- 实现方式:在路由对应的组件上添加过渡效果,并设置不同的nama值
<transition name='slider'>
<div>
foo
</div>
</transition>
- 基于路由的动态过渡效果
- 基于路由的动态过渡:针对路由的跳转不同,设置的路由效果不同
- 实现方式:在组件内监听路由,根据 from 和 to 的路径进行效果判断
<!-- 使用动态的 transition name -->
<transition :name="transitionName">
<router-view></router-view>
</transition>
<!-- 监听路由变化 -->
watch: {
'$route' (to, from) {
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
}
五、从 API 的角度认识vue-router
1 - router-link支持的属性 - 9种
★01 - to
- 接受参数的类型:字符串 | 目标地址的对象
- 必要性:必须
- 作用:用于目标跳转,当被点击后,内部会立刻把 to 的值传递给 router.push()去执行
- 使用实例(官网API):
<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="'home'">Home</router-link>
<!-- 同上 -->
<router-link :to="{ path: 'home' }">Home</router-link>
<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
<!-- 带查询参数,下面的结果为 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}"
>Register</router-link
>
★02 - replace
- 参数:boolean
- 必要性:非必要
- 作用:路由替换,类似于to,但是使用replace时, to的值被传到的不是push()而是执行replace,导航不会留下hsitory记录。
- 使用实例
<router-link :to="{ path: '/abc'}" replace></router-link>
★03 - append
- 参数:boolean
- 必要性:非必须
- 作用:为当前跳转路由添加跟路径。如果当前在 /a下,to=“/b”。不使用append时,跳转的是/b,使用append 后,跳转的是 /a/b;
- 使用实例:
<router-link :to="{ path: 'relative/path'}" append></router-link>
04 - tag
- 参数:字符串
- 必要性:非必须
- 作用:替换导航的渲染标签。默认情况下,导航渲染为a标签,但是可以使用tag指定渲染的标签类型,且导航点击事件不变。
- 使用实例:
<router-link to="/foo" tag="li">foo</router-link>
<!-- 渲染结果 -->
<li>foo</li>
05 - active-class
- 参数:字符串
- 作用:设置路由导航被激活时对应的class类名
- 默认值:
router-link-active - 特别说明:可以使用router的
linkActiveClass 属性来进行全局配置。
★06 - exact
- 参数:boolean
- 作用:在链接上使用精准匹配模式。“是否激活”默认类名的依据是包含匹配
- 使用实例:
<!-- 这个链接只会在地址为 / 的时候被激活 -->
<router-link to="/" exact></router-link>
07 - event
- 参数:字符串 | 字符串数组
- 作用:用来定义触发导航的事件
- 默认值:
click
08 - exact-active-class
- 参数:字符串
- 作用:用来设置当前路由被精准匹配的时候设置的样式
- 默认值:
router-link-exact-actve
09 - aria-current-value
- 类型:‘page’ | ‘step’ | ‘location’ | ‘date’ | ‘time’
- 默认值:’page‘
2 - router的构建选项
01 - routes
interface RouteConfig = {
path: string,
component?: Component,
name?: string,
components?: { [name: string]: Component },
redirect?: string | Location | Function,
props?: boolean | Object | Function,
alias?: string | Array<string>,
children?: Array<RouteConfig>,
beforeEnter?: (to: Route, from: Route, next: Function) => void,
meta?: any,
caseSensitive?: boolean,
pathToRegexpOptions?: Object
}
02 - mode
- 类型:字符串
- 默认值:hash
- 可选值:hash | history | abstract
03 - base
04 - linkActiveClass
- 类型:字符串
- 默认值:
router-link-active - 作用:全局设置
router-link 默认的激活的class
05 - linkExactActiveClass
- 类型:字符串
- 默认值:
router-link-exact-active - 作用:全局设置
router-link 默认的精准激活的 class
06 - scrollBehavior
07 - parseQuery/ stringifyQuery
- 类型:Function
- 作用:提供自定义查询字符串的解析/反解析函数
08 - fallback
六、vue-router 总结

|