前言
Vue Router 是 vue官方的路由管理器,其中v3版本适用于vue2,v4版本适用于vue3。本文单将v3版本
安装和基本使用
安装
npm install vue-router
使用
新建src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
const constantRoutes = [
{
path: "/login",
component: () => import("@/views/login/index")
}
]
const createRouter = () =>
new Router({
routes: constantRoutes,
})
// 创建路由实例,并默认导出
const router = createRouter()
export default router
在main.js中:
import router from "@/router"
new Vue({
router,
render: h => h(App)
}).$mount('#app')
Router 实例属性和方法
属性
- app: Vue实例
- mode: 路由使用的模式("hash" | "history" | "abstract")
- currentRoute: 当前路由信息对象
方法
导航类方法
- push
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了 path,params 会被忽略。
- replace
用法和push类似,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
push和replace方法会返回一个
Promise
- go
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
- back
后退一步,等价于router.go(-1)
- forward
后退一步,等价于router.go(1)
路由钩子相关方法
- beforeEach 全局前置路由
router.beforeEach((to, from, next) => {
// ...
})
一定要调用next方法来 resolve 这个钩子:
next(): 进行管道中的下一个钩子。next(false): 中断当前的导航。next('/')或者next({ path: '/' }): 跳转到一个不同的地址。next(error):如果传入next的参数是一个Error实例,则导航会被终止且该错误会被传递给router.onError()注册过的回调。
- beforeResolve
这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
- afterEach
全局后置钩子
router.afterEach((to, from) => {
// ...
})
添加路由
- addRoute
- 添加一条新路由规则。如果该路由规则有
name,并且已经存在一个与之相同的名字,则会覆盖它。
addRoute(route: RouteConfig): () => void
- 添加一条新的路由规则记录作为现有路由的子路由。如果该路由规则有
name,并且已经存在一个与之相同的名字,则会覆盖它。
addRoute(parentName: string, route: RouteConfig): () => void
- getRoutes 获取所有活跃的路由记录列表。
getRoutes(): RouteRecord[]
路由信息对象(RouteRecord)
一个路由对象 表示当前激活的路由的状态信息。
路由对象是不可变 (immutable) 的,每次成功的导航后都会产生一个新的对象。
路由对象出现在多个地方:
- 在组件内,即
this.$route - 在
$route观察者回调内 router.match(location)的返回值- 导航守卫的参数:
router.beforeEach((to, from, next) => {
// `to` 和 `from` 都是路由对象
})
路由对象属性
- path
字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"。
- params
一个 key/value 对象,包含了动态片段和全匹配片段,如果没有路由参数,就是一个空对象。
- query
一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。
- hash
当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。
- fullPath
完成解析后的 URL,包含查询参数和 hash 的完整路径。
- matched
一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)。
const router = new VueRouter({
routes: [
// 下面的对象就是路由记录
{
path: '/foo',
component: Foo,
children: [
// 这也是个路由记录
{ path: 'bar', component: Bar }
]
}
]
})
- name
当前路由的名称,如果有的话
- redirectedFrom
如果存在重定向,即为重定向来源的路由的名字
RouteConfig
在构建Router时,传入的的参数routes的类型为Array<RouteConfig>
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,
// 2.6.0+
caseSensitive?: boolean, // 匹配规则是否大小写敏感?(默认值:false)
pathToRegexpOptions?: Object // 编译正则的选项
}
内置组件
<router-link>
to: 必填。
<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 渲染结果 -->
<a href="home">Home</a>
<!-- 使用 v-bind 的 JS 表达式 -->
<router-link v-bind: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
>
replace: boolean
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push()
<router-view>
<router-view> 组件是一个 functional 组件,渲染路径匹配到的视图组件。<router-view> 渲染的组件还可以内嵌自己的 <router-view>,根据嵌套路径,渲染嵌套组件。
配合 <transition> 和 <keep-alive> 使用:
<transition>
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition>
注入的属性
通过在 Vue 根实例的 router 配置传入 router 实例,下面这些属性成员会被注入到每个子组件。
-
this.$router
router 实例。
-
this.$route
当前激活的路由信息对象)。这个属性是只读的,里面的属性是 immutable (不可变) 的,不过你可以 watch (监测变化) 它。
组件内守卫
beforeRouteEnter(to, from, next)
不能 访问 this,不过可以通过传一个回调给 next来访问组件实例
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
beforeRouteUpdate(to, from, next)(2.2 新增)
在当前路由改变,但是该组件被复用时调用。 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
beforeRouteLeave
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
奇技淫巧
重置路由
在一般的后台管理系统中,不同的用户可能有不同的路由权限,但又有通用的路由,一般是在登录后,根据用户权限加载不同的路由。那么在用户注销后,如何重置路由呢?
function resetRouter() {
const newRouter = createRouter();
router.matcher = newRouter.matcher; // 重置 路由
}
面试题
params和query传参的使用和区别
- query
类似于get请求,query传过去的参数会拼接到url中。query既可以配合path,也可以配合name使用。
- params
一般params传过去的参数不会显示url上,只能配合name使用,如果出现了path, params会失效。
如果用到了动态路由:‘/user/:id’,传递过去的就是params参数,会拼接显示在地址栏中,比如:/user/13。
如何监听路由参数的变化
- watch
watch: {
'$route'(to, from) {
}
},
- 使用组件守卫
beforeRouteUpdate(to, from, next)