vue3 Router
参考学习笔记来自 作者:小满zs
vue-router_小满zs的博客-CSDN博客
1. 安装配置
(1)安装vue-router
// vue2
npm install vue-router@3 -S
// vue3
npm install vue-router@4 -S
(2)配置路由
- 在src目录下创建router文件夹并新建index.ts
//引入路由对象
import { createRouter, createWebHistory, createWebHashHistory, createMemoryHistory, RouteRecordRaw } from 'vue-router'
//路由数组的类型 RouteRecordRaw
// 定义一些路由
// 每个路由都需要映射到一个组件。
const routes: Array<RouteRecordRaw> = [{
path: '/',
component: () => import('../components/a.vue')
},{
path: '/register',
component: () => import('../components/b.vue')
}]
const router = createRouter({
history: createWebHistory(),
routes
})
// 导出router
export default router
(3)使用路由
- 在main.ts 挂载
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
export const app = createApp(App)
app.use(router)
app.mount('#app')
- 使用路由
<template>
<div>
<h1>使用路由</h1>
<div>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link tag="div" to="/">跳转a</router-link>
<router-link tag="div" style="margin-left:200px" to="/register">跳转b</router-link>
</div>
<hr />
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
</template>
2. 命名路由
为路由提供name属性,有如下优点
- 没有硬编码的 URL
params的自动编码/解码。- 防止你在 url 中出现打字错误。
- 绕过路径排序(如显示一个)
const routes:Array<RouteRecordRaw> = [
{
path:"/",
name:"Login",
component:()=> import('../components/login.vue')
},
{
path:"/reg",
name:"Reg",
component:()=> import('../components/reg.vue')
}
]
<h1>小满最骚</h1>
<div>
<router-link :to="{name:'Login'}">Login</router-link>
<!--改变router-link 的跳转方式-->
<router-link style="margin-left:10px" :to="{name:'Reg'}">Reg</router-link>
</div>
<hr />
3. 编程式导航
(1)字符串模式
import { useRouter } from 'vue-router'
const router = useRouter()
const toPage = () => {
router.push('/reg')
}
(2)对象模式
import { useRouter } from 'vue-router'
const router = useRouter()
const toPage = () => {
router.push({
path: '/reg'
})
}
(3)命名式 路由模式
import { useRouter } from 'vue-router'
const router = useRouter()
const toPage = () => {
router.push({
name: 'Reg'
})
}
(4)a标签跳转
<a href="/reg">rrr</a>
4. 路由历史记录
(1)replace
采用replace进行页面的跳转会同样也会创建渲染新的Vue组件,但是在history中其不会重复保存记录,而是替换原有的vue组件
import { useRouter } from 'vue-router'
const router = useRouter()
const toPage = (url: string) => {
router.replace(url)
}
(2)go
const next = () => {
//前进 数量不限于1
router.go(1)
}
const prev = () => {
//后退
router.go(-1)
}
(3)back
const prev = () => {
//后退
router.back()
}
5. 路由传参
区别
query 传参配置的是 path,而 params 传参配置的是name,在 params中配置 path 无效
query 在路由配置不需要设置参数,而 params 必须设置
query 传递的参数会显示在地址栏中
params传参刷新会无效,但是 query 会保存传递过来的值,刷新不变 ;
(1)Query路由传参
- 传输参数
type Item = {
name:string;
price:number;
id:number;
}
// 省略item的内容
const toDetail = (item: Item) => {
router.push({
path: '/reg',
query: item
})
}
- 接收参数
import { useRoute } from 'vue-router';
const route = useRoute()
cosnt name = route.query?.name
cosnt price = route.query?.price
cosnt id = route.query?.id
(2)Params路由传参
传入的参数页面刷新会丢失
- 传输参数
type Item = {
name:string;
price:number;
id:number;
}
const toDetail = (item: Item) => {
router.push({
name: 'Reg',
params: item
})
}
- 接收参数
import { useRoute } from 'vue-router';
const route = useRoute()
cosnt name = route.query?.name
cosnt price = route.query?.price
cosnt id = route.query?.id
(3)动态路由传参
- 传输参数
const routes:Array<RouteRecordRaw> = [
{
path:"/",
name:"Login",
component:()=> import('../components/login.vue')
},
{
//动态路由参数
path:"/reg/:id",
name:"Reg",
component:()=> import('../components/reg.vue')
}
]
const toDetail = (item: Item) => {
router.push({
name: 'Reg',
params: {
id: item.id
}
})
}
- 接收参数
import { useRoute } from 'vue-router';
import { data } from './list.json'
const route = useRoute()
const item = data.find(v => v.id === Number(route.params.id))
6. 嵌套路由
- 编写路由
const routes: Array<RouteRecordRaw> = [{
path: '/',
name: 'Layout',
component: () => import('../layout/index.vue'),
children: [
{
// 登录
path: '/login',
name: 'Login',
component: () => import('../views/login/index.vue'),
},
{
// 注册
path: '/register',
name: 'Register',
component: () => import('../views/register/index.vue'),
}
]
}
]
- 页面跳转
App.vue
<template>
<router-view />
</template>
<script setup lang="ts"></script>
<style scoped></style>
layout.vue
<template>
<router-link to="/login"><div class="item">登录</div></router-link>
<router-link to="/register"><div class="item">注册</div></router-link>
<!-- 显示路由组件-->
<router-view></router-view>
</template>
8. 命名视图
命名视图可以在同一级(同一个组件)中展示更多的路由视图,而不是嵌套显示。
命名视图可以在同一级(同一个组件)中展示更多的路由视图,而不是嵌套显示。
命名视图的概念非常类似于“具名插槽”,并且视图的默认名称也是 default。
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
const routes: Array<RouteRecordRaw> = [
{
path: "/",
components: {
default: () => import('../components/layout/menu.vue'),
header: () => import('../components/layout/header.vue'),
content: () => import('../components/layout/content.vue'),
}
},
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
对应组件使用
<div>
<router-view></router-view>
<router-view name="header"></router-view>
<router-view name="content"></router-view>
</div>
9. 重定向 redirect
- 字符串形式
const routes: Array<RouteRecordRaw> = [
{
path:'/',
component:()=> import('../components/root.vue'),
redirect:'/user1',
children:[
{
path:'/user1',
components:{
default:()=> import('../components/A.vue')
}
},
{
path:'/user2',
components:{
bbb:()=> import('../components/B.vue'),
ccc:()=> import('../components/C.vue')
}
}
]
}
]
- 对象形式
const routes: Array<RouteRecordRaw> = [
{
path: '/',
component: () => import('../components/root.vue'),
redirect: { path: '/user1' },
children: [
{
path: '/user1',
components: {
default: () => import('../components/A.vue')
}
},
{
path: '/user2',
components: {
bbb: () => import('../components/B.vue'),
ccc: () => import('../components/C.vue')
}
}
]
}
]
- 函数模式
const routes: Array<RouteRecordRaw> = [
{
path: '/',
component: () => import('../components/root.vue'),
redirect: (to) => {
return {
path: '/user1',
query: to.query
}
},
children: [
{
path: '/user1',
components: {
default: () => import('../components/A.vue')
}
},
{
path: '/user2',
components: {
bbb: () => import('../components/B.vue'),
ccc: () => import('../components/C.vue')
}
}
]
}
]
10. 别名 alias
将
/别名为/root,意味着当用户访问/root时,URL 仍然是/user,但会被匹配为用户正在访问/
const routes: Array<RouteRecordRaw> = [
{
path: '/',
component: () => import('../components/root.vue'),
alias:["/root","/root2","/root3"],
children: [
{
path: 'user1',
components: {
default: () => import('../components/A.vue')
}
},
{
path: 'user2',
components: {
bbb: () => import('../components/B.vue'),
ccc: () => import('../components/C.vue')
}
}
]
}
]
11. 路由守卫
(1)全局前置守卫(白名单判断)
- 使用格式
to: Route, 即将要进入的目标 路由对象;
from: Route,当前导航正要离开的路由;
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。next(‘/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
router.beforeEach((to, form, next) => {
console.log(to, form);
next()
})
- 白名单案例
const whileList = ['/', '/login', '/register']
router.beforeEach((to, from, next) => {
let token = localStorage.getItem('token')
//白名单 有值 或者登陆过存储了token信息可以跳转 否则就去登录页面
if (whileList.includes(to.path) || token) {
next()
} else {
next({
path:'/login'
})
}
})
(2)全局后置守卫(加载loading)
- 使用格式
使用场景一般可以用来做loadingBar,
router.afterEach((to,from)=>{
console.log(to, form);
})
- 加载缓冲案例
<template>
<div class="wraps">
<div ref="bar" class="bar"></div>
</div>
</template>
<script setup lang='ts'>
import { ref, onMounted } from 'vue'
let speed = ref<number>(1)
let bar = ref<HTMLElement>()
let timer = ref<number>(0)
const startLoading = () => {
let dom = bar.value as HTMLElement;
speed.value = 1
timer.value = window.requestAnimationFrame(function fn() {
if (speed.value < 90) {
speed.value += 1;
dom.style.width = speed.value + '%'
timer.value = window.requestAnimationFrame(fn)
} else {
speed.value = 1;
window.cancelAnimationFrame(timer.value)
}
})
}
const endLoading = () => {
let dom = bar.value as HTMLElement;
setTimeout(() => {
window.requestAnimationFrame(() => {
speed.value = 100;
dom.style.width = speed.value + '%'
})
}, 500)
}
defineExpose({
startLoading,
endLoading
})
</script>
<style scoped lang="less">
.wraps {
position: fixed;
top: 0;
width: 100%;
height: 2px;
.bar {
height: inherit;
width: 0;
background: blue;
}
}
</style>
main.ts
import loadingBar from './components/loadingBar.vue'
const Vnode = createVNode(loadingBar)
render(Vnode, document.body)
console.log(Vnode);
router.beforeEach((to, from, next) => {
Vnode.component?.exposed?.startLoading()
})
router.afterEach((to, from) => {
Vnode.component?.exposed?.endLoading()
})
12 . 路由元信息 mate
通过路由记录的
meta属性可以定义路由的元信息。使用路由元信息可以在路由中附加自定义的数据
- 权限校验标识
- 路由组件的过渡名称
- 路由组件持久化缓存 (keep-alive) 的相关配置
- 标题名称
- 写入元信息
// ts定义元信息 ,为了更好的处理
declare module 'vue-router' {
interface RouteMeta {
title?: string
}
}
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
component: () => import('@/views/Login.vue'),
// 元信息
meta: {
title: "登录"
}
},
{
path: '/index',
component: () => import('@/views/Index.vue'),
meta: {
title: "首页",
}
}
]
})
13. 路由过渡动效
- vue组件的处理
<!--route路由信息,Component跳转的组件-->
<router-view #default="{route,Component}">
<transition :enter-active-class="`animate__animated ${route.meta.transition}`">
<component :is="Component"></component>
</transition>
</router-view>
- router index.ts的处理
declare module 'vue-router'{
interface RouteMeta {
title:string,
transition:string,
}
}
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
component: () => import('@/views/Login.vue'),
meta:{
title:"登录页面",
transition:"animate__fadeInUp",
}
},
{
path: '/index',
component: () => import('@/views/Index.vue'),
meta:{
title:"首页!!!",
transition:"animate__bounceIn",
}
}
]
})
14. 滚动行为
简介:使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样
- 使用scrollBehavior实现滚动
scrollBehavior 方法接收 to 和 from 路由对象。第三个参数 savedPosition 当且仅当 popstate 导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。
const router = createRouter({
history: createWebHistory(),
scrollBehavior: (to, from, savePosition) => {
// savePosition里的值 为 { left: number, top: number }
console.log(to, '==============>', savePosition);
return new Promise((r) => {
setTimeout(() => {
r({
top: 10000
})
}, 2000);
})
},
scrollBehavior 返回滚动位置的对象信息 =>{ left: number, top: number }
const router = createRouter({
history: createWebHistory(),
scrollBehavior: (to, from, savePosition) => {
return {
top:200
}
},
15. 动态路由
(1)操作路由
- 添加路由
router.addRoute({ path: '/about', component: About })
- 删除路由
// 第一种
const removeRoute = router.addRoute(routeRecord)
removeRoute() // 删除路由如果存在的话
// 第二种
router.addRoute({ path: '/about', name: 'about', component: About })
// 删除路由
router.removeRoute('about')
- 查看路由
- router.hasRoute():检查路由是否存在。
- router.getRoutes():获取一个包含所有路由记录的数组。
(2)代码实现
const initRouter = async () => {
const result = await axios.get('http://localhost:9999/login', { params: formInline });
result.data.route.forEach((v: any) => {
router.addRoute({
path: v.path,
name: v.name,
//这儿不能使用@
component: () => import(`../views/${v.component}`)
})
router.push('/index')
})
console.log(router.getRoutes());
}
本文详细介绍了Vue3中vue-router的安装、配置、使用,包括命名路由、编程式导航、路由历史记录、路由传参、嵌套路由、命名视图、重定向、别名以及路由守卫的用法,是Vue3应用开发的重要参考资料。

251

被折叠的 条评论
为什么被折叠?



