Skip to main content

VueRouter

基础使用

3.x文档 4.x文档

安装

  • 4.x
yarn add vue-router@4

声明路由

  • vue2.x
// src/router/index.ts
import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'

Vue.use(VueRouter)

const routes: Array<RouteConfig> = [
// ...
]

const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})

export default router
  • vue3.x
// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'

const routes: Array<RouteRecordRaw> = [
// ...
]

const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})

export default router

引入路由

main.ts / main.js 中,引入

  • vue3
import router from "@/router";
app.use(router);

路由写法

// 根路由
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'home',
component: () => import(/* webpackChunkName: "home" */ '@views/home.vue')
}
];

// 带loyout的
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'home',
component: () => import(/* webpackChunkName: "home" */ '@views/home.vue'),
children:[{

}]
}
];

路由配置

vue-router的配置以一个对象表示,以创建实例时作为第一个参数给予

const routerOption = {
"配置":"/...."
}
常用字段
publicPath

所有字段https://router.vuejs.org/api/

路由实例

// 获取路由记录
const MATCHED = route.matched;

// 获取该记录的路由个数
const LEN = MATCHED.length;

// 获取倒数第二个路由(也就是当前路由的父级路由)
const ROUTE_PARENT = MATCHED[LEN - 2];

路由钩子

函数名称作用域触发时机
beforeEach全局跳转之前
beforeResolve全局在导航被确认前,同时在组件内守卫和异步路由组件被解析后
afterEach全局在路由跳转完成后触
beforeEnter路由实例上beforeEach触发之后,比beforeResolve要早
onBeforeRouteUpdate组件内组件内的更新,当前路由改变,但是该组件被复用时调用
onBeforeRouteLeave组件内组件内的离开,导航离开该组件的对应路由时调用
beforeRouteEnter组件内3.x 对应beforeEnter

钩子触发顺序:beforeEach(全局) > beforeEnter(独享) > beforeResolve(全局)> afterEach(全局)

代码片段

页面中获取路由

  • vue2
// 通过$route
console.log(this.$route)
  • vue3.x
// 通过导入
import { useRoute } from 'vue-router'

// 刚导入的 useRoute 是一个函数,需要在 setup 里定义一个变量来获取路由信息。
const route = useRoute();

console.log(route)

路由跳转

  • <router-link>标签
<template>
<router-link to="/home">默认生成a标签</router-link>
</template>


<template>
<router-link tag="span" to="/home">生成 span 标签</router-link>
</template>
  • 通过@click
<template>
<span
class="link"
@click="router.push({
name: 'home'
})"
>
首页
</span>
</template>
  • js
router.push({  name: 'home'  })

通过meta存储一些路由状态

const routes: Array<RouteRecordRaw> = [
// 重定向到home,并带上一个query
{
path: '/',
redirect: {
name: 'home',
query: {
from: 'redirect'
}
}
},

// 真正的首页
{
path: '/home',
name: 'home',
component: () => import(/* webpackChunkName: "home" */ '@views/home.vue')
}
]

// 最终访问的地址就是 https://chengpeiquan.com/home?from=redirect

像这样带有来路参数的,你就可以在 “百度统计” 或者 “CNZZ统计” 之类的统计站点查看来路的流量

通过路由控制角色权限

const routes: Array<RouteRecordRaw> = [
// 访问主域名时,根据用户的登录信息,重定向到不同的页面
{
path: '/',
redirect: () => {
// LOGIN_INFO是当前用户的登录信息,你可以从localStorage或者Vuex读取
const GROUP_ID: number = LOGIN_INFO.groupId;

// 根据组别id进行跳转
switch (GROUP_ID) {
// 管理员,跳去仪表盘
case 1:
return '/dashboard';

// 普通用户,跳去首页
case 2:
return '/home';

// 其他都认为未登录,跳去登录页
default:
return '/login'
}
}
}
]

路由全局钩子

import router from "./routes/index.ts"

// 3.x
router.beforeEach(( to, from, next )=>{ /*...业务代码*/ next() })
router.beforeEach(( to, from, next )=>{ /*...业务代码*/ next() })
router.beforeEach(( to, from, next )=>{ /*...业务代码*/ next() })
routes.beforeEnter(( to, from, next )=>{ /*...业务代码*/ next() })
onBeforeRouteUpdate
onBeforeRouteLeave
beforeRouteEnter

// 4.x
// 4.x 去掉了 next,再也不用因为忘记使用next而出现奇怪的BUG了
// 直接return就相当于调用next()
router.beforeEach(( to, from )=>{})
router.beforeResolve(( to, from )=>{})
router.afterEach(( to, from )=>{})
routes.beforeEnter = ( to, from )=>{}

// 组件内部使用的钩子
onBeforeRouteUpdate
onBeforeRouteLeave

路由钩子使用

  • 全局
import { defineComponent } from 'vue'
import { useRouter } from 'vue-router'

export default defineComponent({
setup () {

// 此处获取组件路由实例
const router = useRouter();

// 调用全局钩子
router.beforeEach((to, from) => {
// ...
})

}
})
  • 组件
const routes: Array<RouteRecordRaw> = [
{
path: '/home',
name: 'home',
component: () => import(/* webpackChunkName: "home" */ '@views/home.vue'),

// 在这里添加单独的路由守卫
beforeEnter: (to, from) => {
document.title = '程沛权 - 养了三只猫';
}
}
];
import { onBeforeRouteUpdate, onBeforeRouteLeave } from "vue-route"

路由监听

  • watchEffect
import { defineComponent, watchEffect } from 'vue'
import { useRoute } from 'vue-router'

export default defineComponent({
setup () {
const route = useRoute();

// 获取文章详情
const getArticleDetail = (): void => {
// 直接通过路由的参数来获取文章id
const ARTICLE_ID: number = Number(route.params.id) || 0;
console.log('文章id是:', ARTICLE_ID);

// 请求文章内容
// 此处略...
}

// 直接监听包含路由参数的那个函数
// 对比 watch 的使用, watchEffect 在操作上更加简单,把包含要被监听数据的函数作为入参即可
watchEffect(getArticleDetail);
}
})
  • watch
import { defineComponent, watch } from 'vue'
import { useRoute } from 'vue-router'

export default defineComponent({
setup () {
const route = useRoute();

// 监听整个路由
watch(
route,
(to, from) => {
// 处理一些事情
// ...
})

// 监听某个参数变化
watch(
() => route.query.id,
() => {
console.log('监听到query变化');
}
)

}
})
  • 第一个参数传入整个路由
  • 第二个参数是个callback,可以获取to和from来判断路由变化情况。

新旧版变化

Typescript 类型

vue-router@3vue-router@4
RouteConfigRouteRecordRaw
LocationRouteLocation
RouteRouteLocationNormalized