VueRouter
基础使用
安装
- 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 | ||
路由实例
// 获取路由记录
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@3 | vue-router@4 |
---|---|
RouteConfig | RouteRecordRaw |
Location | RouteLocation |
Route | RouteLocationNormalized |