Vue Router 是 Vue.js 官方提供的路由管理器,它与 Vue.js 核心深度集成,使得构建单页面应用(SPA)变得容易。在单页面应用中,所有视图和组件都通过路由来管理和切换,而不是传统的整页刷新。
在本课文中将介绍Vue Router的一些常用方法。
视频🎞️
安装
新建项目
npm create vite@latest
创建项目时选择Customize with create-vue,并且选择引入 Vue Router 进行单页面应用开发,其他选项可以按需进行选择。
这样创建的项目已经初始化好Vue Router文件配置。可以开箱即用。
已有项目
- 在终端中输入
npm install vue-router@4
- 创建
router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
... // 页面路由配置
]
})
export default router
- 在main.js中引入
router/index.js
,并且通过app.use()
明确地安装路由功能
... ...
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 导入创建的js
const app = createApp(App)
app.use(router) // 安装路由功能
app.mount('#app')
页面组件的内容将在<RouterView/>
中渲染。
routes配置
history模式配置
HTML5 模式(推荐)
createWebHistory()
url效果:http://example.com/myroute
url看上去和正常的链接一样干净,需要注意在生产环境中要进行配置,使得任何非静态资源请求(如 /about、/dashboard 等)都被重定向到应用的入口 HTML 文件(通常是 index.html),否则会出现404。
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(), // HTML5 模式
routes: [
// ...
]
})
export default router
Hash 模式
createWebHashHistory()
url效果:http://example.com/#/myroute
它在内部传递的实际 URL 之前使用了一个哈希字符(#)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。但是seo效果不好。
import { createRouter, createWebHashHistory} from 'vue-router'
const router = createRouter({0 history: createWebHashHistory(), // Hash 模式
routes: [
// ...
]
})
export default router
路由组件导入方法
静态导入
静态导入会在应用启动时随主资源一同加载,当模块多的时候容易造成首屏加载时间过长,
import { createRouter, createWebHistory } from 'vue-router'
// 静态导入页面组件
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
// 使用引入的路由组件
component: HomeView
}
]
})
export default router
懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。
如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。
import { createRouter, createWebHistory } from 'vue-router'
// 动态导入页面组件
const AboutView = () => import('../views/AboutView.vue')
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/about',
name: 'about',
component: AboutView
}
]
})
export default router
路由传参
方式一:query
使用query传参会跟传统的参数一样,?
跟在url后面,多个参数以 &
隔开。
import {useRouter} from "vue-router";
const $router = useRouter()
function onToView(){
$router.push({path:'/user',query:{text:'UserView'}})
// $router.push('/user?text=UserView') // 自己拼接url
}
方式二:params
需要先在路由配置中使用 :
+参数名
来配置参数
routes: [
// ...
{
path: '/user/:id', //配置id参数
name: 'user',
component: () => import('../views/UserView.vue'),
}
// ...
]
当使用path时,params属性会被忽略,所以要么使用name属性,或者自己拼接url;
import {useRouter} from "vue-router";
const $router = useRouter()
function onToView(){
let id = 0
$router.push({name:'user',params:{id:id}})
// $router.push(`/user/${id}`) // 自己拼接url
}
元信息
当需要一些信息附加到路由上时,可以通过配置路由元信息来实现,比如是否需要登录才能访问,设置页面切换过渡效果,是否要缓存该页面…
routes: [
// ...
{
path: '/',
name: 'home',
meta: {checkLogin: true}, // 配置元信息
component: () => import('../views/HomeView.vue'),
}
// ...
]
单独配置元信息不会起到任何作用,还需要写相应的代码来达成期望效果;
例如通过元信息配置部分页面需要使用<keep-alive/>
缓存
<template> <router-view v-slot="{ Component }"> <keep-alive :include="cacheRouteName"> <component :key="$route.name" :is="Component" /> </keep-alive> </router-view> </template> <script setup> import { useRouter } from "vue-router" const router = useRouter() // 从路由中获取带有缓存元数据的路由名称 const cacheRouteName = router .getRoutes() .filter((item) => item.meta?.cache) // 过滤出带有缓存元数据的路由 .map((item) => item.name) // 提取路由名称 </script>
路由守卫
路由守卫主要用来通过跳转或取消的方式守卫导航。
每个路由守卫接收两个参数
to
:代表即将要进入的路由from
:代表当前即将离开的路由
可选的第三个参数next
当设置该参数时,需要确保在路由守卫中执行一次next()
若未调用,则页面导航将被阻塞,无法正常跳转。它可以出现多次,但应只执行一次。
next方法中可以传递path来重定向到其它页面
router.beforeEach((to, from, next) => {
if (/* 用户未登录 */) {
next('/login'); // 通过 next 方法重定向到登录页
} else {
next(); // 继续正常跳转
}
});
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [
// 定义路由
{
path: '/home',
component: Home,
// 路由独享的守卫
beforeEnter: (to, from, next) => {
// 在进入路由前执行的逻辑
// 可以进行权限验证等操作
next(); // 调用next()继续路由导航
}
},
// 其他路由定义
]
});
// 全局前置路由守卫
router.beforeEach((to, from, next) => {
// 在进入每个路由前执行的逻辑
// 可以进行全局的权限验证等操作
next(); // 调用next()继续路由导航
});
export default router;