Vue.js 的官方路由,为 Vue.js 提供富有表现力、可配置的、方便的路由。
一、安装
$ npm i vue-router
注意:
- Vue@3.x 配套 vue-router@4.x 使用
- Vue@2.x 配置 vue-router@3.x 使用
二、使用路由
可在 src 目录下创建 `views` 目录,用于放置应用中的页面级组件(略)
在 src 目录下创建 `router` 目录,用于管理路由,然后在 `router` 下的入口 `index.js` 中:
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
// 创建 VueRouter 对象实例
const router = createRouter({
history: createWebHashHistory(), // 设置路由模式 hash: createWebHashHistory()
routes: [ // 路由表
{
path: '/home', // 路由路径
component: Home, // 对应渲染的路由组件
},
{
path: '/login',
component: Login,
},
{
path: '/about',
component: () => import('../views/About.vue'), // 路由懒加载
},
],
})
// 导出创建的路由对象实例
export default router
在 src 目录下应用入口 main.js 文件中,引入创建好的 router,并使用:
import { createApp } from 'vue'
import App from './App.vue'
// 引入路由对象
import router from './router'
// 创建应用实例
const app = createApp(App)
// 使用路由
app.use(router)
// 挂载
app.mount('#app')
在 `app.use(router)` 使用路由后,组件中可使用到路由内置的两个组件:
<router-link>: 链接,可点击跳转页面
<router-view>: 视图,用于显示渲染路由组件
在 App.vue 中创建链接与视图:
<template>
<div class="app">
App
<div>
<!-- 链接 -->
<router-link to="/home">首页</router-link> |
<router-link to="/login">登录</router-link> |
<router-link to="/about">关于</router-link> |
</div>
<!-- 视图 -->
<router-view />
</div>
</template>
在 app.use(router) 使用路由后,除了 <router-link> 与 <router-view> 两个组件外,在组件中我们还可以使用到注入的两个属性:
$router: 引用的是整个路由对象实例(可理解为 createRouter() 所创建的路由对象)
$route: 引用的是当前正访问的路由信息(也是一个对象结构)
三、路由传参
1、查询字符串
利用 `?` 将需要在页面跳转时传递的参数数据`key=value`键值对拼接在 url 资源路径名称后,如:
<router-link to="/login?username=xiaoming&password=123456">登录</router-link>
在目标组件中,要获得到路由路径中传递的查询字符串参数,调用 $route 的 query 属性:
console.log(this.$route.query)
2、动态路径参数
需要在路由表进行配置时,在路径名称后以 `:` 加路径参数进行配置,如:
{
path: '/detail/:id', // 配置一个动态的路径参数,要以 / 分隔层级,使用 : 加参数名定义路径参数
component: () => import('../views/Detail.vue'),
},
在进行路由跳转时,路由资源访问及传递参数的链接:
<router-link to="/detail/prod001">商品1</router-link>
在目标组件(页面)中,调用 $route 的 params 属性获取路径参数,如:
this.id = this.$route.params.id
动态的路径参数如果需要定义为可选参数,可以使用正则的 `?` 号标记:
{
path: '/detail/:id?', // 使用?号标记id参数,表示这是一个可选的参数(可传递可不传递)
component: () => import('../views/Detail.vue'),
},
四、匹配所有资源
在路由路径配置时:
// 将匹配所有内容并将其放在 `route.params.pathMatch` 下
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
五、嵌套路由
嵌套路由通常对应于组件的嵌套
通常用于需要复用组件逻辑的情况。
利用路由配置中的 children 属性来定义嵌套路由:
{
path: '/layout',
component: () => import('../layout/Layout.vue'),
children: [ // 子路由,嵌套路由
{
path: 'intro', // 完整路由路径 /layout/intro
component: () => import('../layout/Introduction.vue'),
children: [],
},
{
path: 'install', // 完整路由路径 /layout/install
component: () => import('../layout/Install.vue'),
},
],
},
一般嵌套路由的 `path` 定义时不以 `/` 开头,其完整路径会自动将父级的路径作为前缀拼接使用。路径中如果以 `/` 开头,是绝对路径的写法,一般表示是 `WebServer` 服务器的根路径。
六、命名路由
是在路由定义配置时,添加 `name` 属性,注意要保证 name 命名的唯一性。
好处:
> 没有硬编码的 URL。
> params 的自动编码/解码。
> 防止你在 URL 中出现打字错误。
> 绕过路径排序,例如展示一个匹配相同路径但排序较低的路由。
七、编程式导航
在 JS 逻辑中实现导航(页面跳转)。
在 vue-router 中实现编程式的导航,需要在组件中调用到注入组件中的 `$router` 属性。调用相关 API 方法实现导航:
- push(arg)
- replace(arg)
- go(n)
- back()
- forward()
1、push()
调用 push() 会向 history 栈中添加一条访问的历史记录,在点击浏览器后退按钮时,能够回到之前的 URL。
该方法的参数可以是一个字符串路径,或者一个描述地址的对象:
// 字符串路径
router.push('/users/eduardo')
// 带有路径的对象
router.push({ path: '/users/eduardo' })
// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })
// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })
// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })
传递字符串参数时,如果有通过 url 携带的参数数据需要传递到目标组件中,则使用 `?` 直接拼接,或拼接路径参数传递即可。
传递对象参数时,对象中可包含的属性有: `path`、`name`、`query`、`params`、`hash`等。注意,`path` 属性与 `params` 属性不能共存。如果需要显式传递路径参数,通常是配合 `name` 属性与 `params` 属性一起使用。
2、replace()
replace() 与 push() 作用基本一致,不同之处在于 replace() 在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代(替换)了当前的条目。在后退时,使用 replace() 跳转的是无法回到原页面。
八、命名视图
为 <router-view /> 添加 name 属性,即为命名视图。
同时 (同级) 展示多个视图,而不是嵌套展示,则可以使用命名视图。
如果 `router-view` 没有设置名字,那么默认为 default。
九、重定向与别名
重定向使用 `redirect` 进行配置,别名使用 `alias` 进行配置。
重定向是会重新发起一次新的资源导航切换跳转,所以地址栏会发生改变;而别名是一个资源可以由两个不同的名称进行引用,使用任何一个名称访问均可,访问时地址栏不会变化。
十、导航守卫
作用: 主要用来通过跳转或取消的方式守卫导航。
在导航切换跳转的过程中,会经历一系列的步骤,在这一系列步骤的某个阶段,可执行到开发者指定的特定代码。提供了一系列的钩子函数。
分类:
- 全局
- 路由独享
- 组件级
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 守卫。(组件级)
- 调用全局的 beforeEach 守卫。(全局的)
- 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。(组件级)
- 在路由配置里调用 beforeEnter。(路由独享的)
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。(组件级)
- 调用全局的 beforeResolve 守卫(2.5+)。(全局的)
- 导航被确认。
- 调用全局的 afterEach 钩子。(全局的)
- 触发 DOM 更新。
- 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
1、全局的导航守卫
beforeEach(): 全局前置守卫,在进入每个页面时,都会执行经过该导航守卫钩子。经常会在该守卫钩子中进行页面访问权限的拦截。
beforeResolve(): 全局解析守卫
afterEach(): 全局后置钩子
2、路由独享的导航守卫
指的是在路由配置时,配置选项中定义的钩子函数
beforeEnter()
3、组件级的导航守卫
就是当 app.use(router) 后,注入到组件内部的导航守卫钩子:
beforeRouteEnter(): 注意这个函数中的 this
beforeRouteUpdate(): 组件复用时调用到
beforeRouteLeave()