vue-router查漏补缺

news2025/2/27 17:26:18

一、动态路由匹配

1.带参数的动态路由匹配
import User from './User.vue'

// 这些都会传递给 `createRouter`
const routes = [
  // 动态字段以冒号开始
  { path: '/users/:efg', component: User },
]

这种方式的路由会匹配到/users/abc或者/users/123,路径参数用冒号:表示,并且将值abc放在route.params里面

//当前路由/users/abc
import {useRoute} from "vue-router";
const route = useRoute();
console.log(route.params,"route");  // {efg:abc}

注意: 这种路径匹配不上 /users/abc/name,需要把path修改为/users/:efg/name

const routes = [
  // 动态字段以冒号开始
  { path: '/users/:efg/name', component: User },  //这样能匹配上,
]
console.log(route.params,"route");  //{efg:abc}
//或者下面这种写法====================================================================
const routes = [
  // 动态字段以冒号开始
  { path: '/users/:efg/:hhh', component: User },  //这样能匹配上,
]
console.log(route.params,"route");  //{efg:abc,hhh:name}

具体匹配规则

匹配模式匹配路径route.params
/users/:username/users/eduardo{ username: ‘eduardo’ }
/users/:username/posts/:postId/users/eduardo/posts/123{ username: ‘eduardo’, postId: ‘123’ }
/users-:id(.*)/users-/123{ id: ‘123’ }

需要注意的是,如果路由从/users/abc变到/users/123,因为都是用的同一个component,所以会重复使用,并不会销毁,这就会导致页面不会重新创建,不会触发生命周期钩子,也获取不到最新的route.params,需使用下面的方法来解决

<script setup>
import { watch } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()

watch(() => route.params.id, (newId, oldId) => {
  // 对路由变化做出响应...
})
</script>

也可以使用beforeRouteUpdate导航守卫

<script setup>
import { onBeforeRouteUpdate } from 'vue-router'
// ...

onBeforeRouteUpdate(async (to, from) => {
  // 对路由变化做出响应...
  userData.value = await fetchUser(to.params.id)
})
</script>
2.捕获所有路由或 404 Not found 路由

常规参数只匹配url片段之间的字符,用/分隔。如果我们想匹配任意路径,我们可以使用自定义的路径参数正则表达式,在路径参数后面的括号中加入 正则表达式

const routes = [
  // 将匹配所有内容并将其放在 `route.params.pathMatch` 下
  { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
    // 将匹配以 `/user-` 开头的所有内容,并将其放在 `route.params.afterUser` 下
  { path: '/user-:afterUser(.*)', component: UserGeneric },
]

注意: 这种匹配方式的优先级最低,优先级高低为 /test > /test/:id > /test:afterUser(.*)* > /:pathMatch(.*)*,就一句话,越精准的匹配上,优先级越高

二、路由的匹配语法

路由的匹配可以通过正则来更加灵活、精确的匹配

const routes = [
  // /:orderId -> 仅匹配数字
  { path: '/:orderId(\\d+)' },
  // /:productName -> 匹配其他任何内容
  { path: '/:productName' },
]
const routes = [
  // /:chapters ->  匹配 /one, /one/two, /one/two/three, 等
  { path: '/:chapters+' },
  // /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等
  { path: '/:chapters*' },
]

这个具体就看官网了,难得写了

1.Sensitive 与 strict 路由配置

默认情况下,所有路由是不区分大小写的,并且能匹配带有或不带有尾部斜线的路由。例如,路由/users将匹配 /users/users/、甚至 /Users/。这种行为可以通过strictsensitive选项来修改,它们既可以应用在整个全局路由上,又可以应用于当前路由上:

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // 将匹配 /users/posva 而非:
    // - /users/posva/ 当 strict: true
    // - /Users/posva 当 sensitive: true
    { path: '/users/:id', sensitive: true },
    // 将匹配 /users, /Users, 以及 /users/42 而非 /users/ 或 /users/42/
    { path: '/users/:id?' },
  ],
  strict: true, // 严格匹配,不允许带有尾部斜线
  sensitive: true, //区分大小写
})

三、嵌套路由

在子路由中的path加/和不加有很大的区别,以 /开头的嵌套路径将被视为根路径

  {
    path: "/test",
    name: "test",
    hidden: false,
    component: () => import("@/pages/test/test.vue"),
    children: [
      {
        //path: "center",  //path不加 / ,将匹配到http://localhost:9527/#/test/center
        path: "/center",  //path加 /,将匹配到http://localhost:9527/#/center
        name: "center",
        component: () => import("@/pages/center/center.vue"),
      },
    ],
  },
1.忽略父组件(4.1+版本)
const routes = [
  {
    path: "/test",
    name: "test",
    hidden: false,
    // component: () => import("@/pages/test/test.vue"),
    children: [
      {
        path: "center",
        name: "center",
        component: () => import("@/pages/center/center.vue"),
      },
    ],
  },
]

由于父级没有指定路由组件,顶级<router-view>将跳过父级并仅使用子路由组件。
在这里插入图片描述

  {
    path: "/test",
    name: "test",
    hidden: false,
    component: () => import("@/pages/test/test.vue"),
    children: [
      {
        path: "center",
        name: "center",
        component: () => import("@/pages/center/center.vue"),
      },
    ],
  },

在这里插入图片描述

四、命名路由

当创建一个路由时,可以选择给路由一个name

const routes = [
  {
    path: '/user/:username',
    name: 'user', 
    component: User
  }
]

这个路由name在整个路由中是唯一的,可以通过router.push({ name: 'user', params: { username: 'erina' } })这种方式来进行路由跳转,将创建一个指向 /user/erina的链接。可以通过route.params来获取参数,使用name有很多优点:

  • 没有硬编码的 URL
  • params的自动编码/解码
  • 防止你在 URL 中出现打字错误
  • 不用关心路由嵌套,就算是100层也能直接使用name来直接定位

命名路由通过params来传递参数,一定要使用动态路由,这样才能获取到传递的参数

### 五、命名视图
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果`router-view`没有设置名字,那么默认为 default

```html
<router-view class="view left-sidebar" name="LeftSidebar" />
<router-view class="view main-content" />
<router-view class="view right-sidebar" name="RightSidebar" />
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      components: {
        default: Home,
        // LeftSidebar: LeftSidebar 的缩写
        LeftSidebar,
        // 它们与 `<router-view>` 上的 `name` 属性匹配
        RightSidebar,
      },
    },
  ],
})

六、别名

重定向是指当用户访问 /home 时,URL 会被 / 替换,然后匹配成 /。那么什么是别名呢?

/别名为/home,意味着当用户访问/home 时,URL 仍然是 /home,但会被渲染/的内容。

const routes = [
  {
    path: '/users',
    component: UsersLayout,
    children: [
      // 为这 3 个 URL 呈现 UserList
      // - /users
      // - /users/list
      // - /people
      { path: '', component: UserList, alias: ['/people', 'list'] },
    ],
  },
]

如果路由有参数,请确保在任何绝对别名中包含它们:

const routes = [
  {
    path: '/users/:id',
    component: UsersByIdLayout,
    children: [
      // 为这 3 个 URL 呈现 UserDetails
      // - /users/24
      // - /users/24/profile
      // - /24
      { path: 'profile', component: UserDetails, alias: ['/:id', ''] },
    ],
  },
]

注意 如果别名和另一个路由path相同,谁在前面谁显示

const routes = [
 {
        path: "/homePage",
        name: "homePage",
        alias: "/webgpu",  //就算下面有/webgpu的路由,一样会渲染/homePage的内容
        component: () => import("@/pages/home/children/homePage.vue"),
      },
      {
        path: "/webgpu",
        name: "webgpu",
        component: () => import("@/pages/home/children/webgpu.vue"),
      },
]

七、路由组件传参

props设置为true时,route.params将被设置为组件的props

const routes = [
  { path: '/user/:id', component: User, props: true }
]

路由为/user/123456

<!-- User.vue -->
<script setup>
defineProps({
  id: String   //值为123456
})
</script>

<template>
  <div>
    User {{ id }}
  </div>
</template>

props是一个对象时,它将原样设置为组件props。当 props 是静态的时候很有用。

const routes = [
  { path: '/user/:id', component: User, props: {username:"admin"}}
]

可以创建一个返回props的函数。这允许你将参数转换为其他类型,将静态值与基于路由的值相结合等等。

const routes = [
  {
    path: '/search',
    component: SearchUser,
    props: route => ({ abc: "13456" })
  }
]

全局传参

<RouterView v-slot="{ Component }">
  <component
    :is="Component"
    view-prop="value"
   />
</RouterView>

这样每一个路由组件都能获取到view-prop参数

八、路由守卫

1. 全局路由前置守卫
const router = createRouter({ ... })

router.beforeEach((to, from) => {
  //通过一个路由地址重定向到一个不同的地址,如同调用 router.push(),且可以传入诸如 replace: true 或 name: 'home' 之类的选项。它会中断当前的导航,同时用相同的 from 创建一个新导航。
   //  return { name: 'Login' } 
   //返回true或者返回undefine来调用下一个守卫
   //return true
  // 返回 false 以取消导航
  return false
})

如果遇到了意料之外的情况,可能会抛出一个Error。这会取消导航并且调用router.onError()注册过的回调

2. 全局解析守卫

你可以用router.beforeResolve注册一个全局守卫。这和router.beforeEach类似,因为它在每次导航时都会触发,不同的是,解析守卫刚好会在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用

router.beforeResolve((to,from) =>{
    console.log(to,from,"beforeResolve");
});
3. 在守卫内的全局注入

从 Vue 3.3 开始,你可以在导航守卫内使用inject()方法

// main.ts
const app = createApp(App)
app.provide('global', 'hello injections')

// router.ts or main.ts
router.beforeEach((to, from) => {
  const global = inject('global') // 'hello injections'
  // a pinia store
  const userStore = useAuthStore()
  // ...
})
4. 路由独享的守卫

beforeEnter守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发。例如,从 /users/2 进入到 /users/3 或者从 /users/2#info 进入到 /users/2#projects。它们只有在 从一个不同的 路由导航时,才会被触发。

function removeQueryParams(to) {
  if (Object.keys(to.query).length)
    return { path: to.path, query: {}, hash: to.hash }
}

function removeHash(to) {
  if (to.hash) return { path: to.path, query: to.query, hash: '' }
}

const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: [removeQueryParams, removeHash],
  },
  {
    path: '/about',
    component: UserDetails,
    beforeEnter: [removeQueryParams],
  },
]

当配合嵌套路由使用时,父路由和子路由都可以使用beforeEnter。如果放在父级路由上,路由在具有相同父级的子路由之间移动时,它不会被触发。例如:

const routes = [
  {
    path: '/user',
    beforeEnter() {
      // ...
    },
    children: [
      { path: 'list', component: UserList },
      { path: 'details', component: UserDetails },
    ],
  },
]

示例中的 beforeEnter 在 /user/list /user/details 之间移动时不会被调用,因为它们共享相同的父级路由。如果我们直接将 beforeEnter 守卫放在details路由上,那么在这两个路由之间移动时就会被调用。

5. 完整的导航解析流程
  • 导航被触发。
  • 在失活的组件里调用 beforeRouteLeave 守卫。
  • 调用全局的 beforeEach 守卫。
  • 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。
  • 在路由配置里调用 beforeEnter。
  • 解析异步路由组件。
  • 在被激活的组件里调用 beforeRouteEnter。
  • 调用全局的 beforeResolve 守卫(2.5+)。
  • 导航被确认。
  • 调用全局的 afterEach 钩子。
  • 触发 DOM 更新。
  • 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

九、RouterView 插槽

RotuerView 组件暴露了一个插槽,可以用来渲染路由组件:

<router-view v-slot="{ Component }">
  <keep-alive>
    <component :is="Component" />
  </keep-alive>
</router-view>

十、滚动行为

使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。
注意: 这个功能只在支持 history.pushState 的浏览器中可用。

const router = createRouter({
  history: createWebHashHistory(),
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
  	return {
  		top:10,
  		behavior: 'smooth',  //让滚动更平滑,不是直接跳到这个位置,而是慢慢滚动到这个位置
  	}
    // return 期望滚动到哪个的位置
  }
})

也可以通过 el 传递一个 CSS 选择器或一个 DOM 元素。在这种情况下,top 和 left 将被视为该元素的相对偏移量

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // 始终在元素 #main 上方滚动 10px
    return {
      // 也可以这么写
      // el: document.getElementById('main'),
      el: '#main',
      // 在元素上 10 像素
      top: 10,
    }
  },
})

十一、导航故障

当使用router-link组件时,Vue Router会自动调用router.push来触发一次导航。虽然大多数链接的预期行为是将用户导航到一个新页面,但也有少数情况下用户将留在同一页面上:

  • 用户已经位于他们正在尝试导航到的页面
  • 一个导航守卫通过调用return false中断了这次导航
  • 当前的导航守卫还没有完成时,一个新的导航守卫会出现了
  • 一个导航守卫通过返回一个新的位置,重定向到其他地方 (例如,return ‘/login’)
  • 一个导航守卫抛出了一个Error

注意:导航是异步的
如果导航被阻止,导致用户停留在同一个页面上,由router.push返回的Promise的解析值将是Navigation Failure。否则,它将是一个falsy值(通常是undefined)。这样我们就可以区分我们导航是否离开了当前位置:

const navigationResult = await router.push('/my-profile')

if (navigationResult) {
  // 导航被阻止
} else {
  // 导航成功 (包括重新导航的情况)
  this.isMenuOpen = false
}

Navigation Failure 是带有一些额外属性的Error实例,这些属性为我们提供了足够的信息,让我们知道哪些导航被阻止了以及为什么被阻止了。要检查导航结果的性质,请使用isNavigationFailure函数:

import { NavigationFailureType, isNavigationFailure } from 'vue-router'

// 试图离开未保存的编辑文本界面
const failure = await router.push('/articles/2')

if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
  // 给用户显示一个小通知
  showToast('You have unsaved changes, discard and leave anyway?')
}

NavigationFailureType有三种值

  • aborted:在导航守卫中返回false中断了本次导航。
  • cancelled: 在当前导航完成之前又有了一个新的导航。比如,在等待导航守卫的过程中又调用了router.push
  • duplicated:导航被阻止,因为我们已经在目标位置了。

十二、动态路由

router.addRoute({ name: 'admin', path: '/admin', component: Admin })
router.addRoute('admin', { path: 'settings', component: AdminSettings })

动态添加路由有两种方式,上面的第一种是直接添加在最顶级路由,第二种方式传入一个路由的name,可以把第二个参数的路由放在它的children属性中,用于添加嵌套路由,相当于

router.addRoute({
  name: 'admin',
  path: '/admin',
  component: Admin,
  children: [{ path: 'settings', component: AdminSettings }],
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2257995.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu22.04深度学习环境安装【Anaconda+Pycharm】

anaconda可以提供多个独立的虚拟环境&#xff0c;方便我们学习深度学习&#xff08;比如复现论文&#xff09;&#xff1b; Pycharm编辑器可以高效的编写python代码&#xff0c;也是一个很不错的工具。 下面就记录下Ubuntu22.04的安装流程&#xff1a; 1.Anaconda安装 下载Ana…

三维测量与建模笔记 - 6.2 结构光三维成像简介

简介 双目视觉系统中&#xff0c;找到左右图像中的同名点是很困难的。 即便是经过了极线校正&#xff0c;也存在很多问题比如高光等造成无匹配。对于结构光方案来说&#xff0c;找到同名点的过程会相对简单些。 结构光方案中&#xff0c;会增加一个投射器&#xff0c;将编码后的…

this version of the Java Runtime only recognizes class file versions up to 52.0

问题描述 Exception in thread "main" java.lang.UnsupportedClassVersionError: com/xxx/Main has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versi…

【开源免费】基于SpringBoot+Vue.JS在线办公系统(JAVA毕业设计)

本文项目编号 T 001 &#xff0c;文末自助获取源码 \color{red}{T001&#xff0c;文末自助获取源码} T001&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

【WRF理论第十三期】详细介绍 Registry 的作用、结构和内容

目录 1. Introduction&#xff1a;介绍 Registry 的作用和功能。2. Registry Contents&#xff1a;详细描述 Registry 的结构和内容&#xff0c;包括各个部分的条目类型。2.1. DIMSPEC ENTRIES&#xff08;维度规格条目&#xff09;2.2. STATE ENTRIES&#xff08;状态变量条目…

Redis篇-4--原理篇3--Redis发布/订阅(Pub/Sub)

1、概述 Redis 发布/订阅&#xff08;Publish/Subscribe&#xff0c;简称 Pub/Sub&#xff09;是一种消息传递模式&#xff0c;允许客户端订阅一个或多个通道&#xff08;channel&#xff09;&#xff0c;并接收其他客户端发布到这些通道的消息。 2、Redis 发布/订阅的主要概…

[大数据]Hudi编译集成

1. Hudi概述 1.1 Hudi简介 What is Apache Hudi Apache Hudi is the next generation streaming data lake platform. Apache Hudi brings core warehouse and database functionality directly to a data lake. Hudi provides tables, transactions, efficient upserts/dele…

Redis 数据结构(一)—字符串、哈希表、列表

Redis&#xff08;版本7.0&#xff09;的数据结构主要包括字符串&#xff08;String&#xff09;、哈希表&#xff08;Hash&#xff09;、列表&#xff08;List&#xff09;、集合&#xff08;Set&#xff09;、有序集合&#xff08;Sorted Set&#xff09;、超日志&#xff08…

Cisco Packet Tracer | Cisco Packet Tracer - VLAN 实验 - 交换机的 VLAN 划分

关注这个工具的其它相关笔记&#xff1a;Cisco Packet Tracer —— 使用教程合集-CSDN博客 0x01&#xff1a;VLAN 划分 - 单个交换机 0x0101&#xff1a;拓扑搭建流程 从软件底部拖出一台交换机&#xff08;笔者选择的型号是 2960 IOS15&#xff09;&#xff1a; 然后再拖出四…

元宇宙时代的社交平台:Facebook的愿景与实践

随着科技的不断进步&#xff0c;元宇宙&#xff08;Metaverse&#xff09;这一概念逐渐走进了人们的视野。作为全球最大的社交平台之一&#xff0c;Facebook&#xff08;现Meta&#xff09;在这场元宇宙革命中扮演着重要角色。Meta不仅在不断扩展其社交平台的边界&#xff0c;还…

Nignx部署Java服务测试使用的Spring Boot项目Demo

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

计算机网络ENSP课设--三层架构企业网络

本课程设计搭建一个小型互联网&#xff0c;并模拟Internet的典型Web服务过程。通过此次课程设计&#xff0c;可以进一步理解Internet的工作原理和协议过程&#xff0c;并提高综合知识的运用能力和分析能力。具体目标包括&#xff1a; &#xff08;1&#xff09;掌握网络拓扑的…

记一次:使用C#创建一个串口工具

前言&#xff1a;公司的上位机打不开串口&#xff0c;发送的时候设备总是关机&#xff0c;因为和这个同事关系比较好&#xff0c;编写这款软件是用C#编写的&#xff0c;于是乎帮着解决了一下&#xff08;是真解决了&#xff09;&#xff0c;然后整理了一下自己的笔记 一、开发…

SQL 获取今天的当月开始结束范围:

使用 GETDATE() 结合 DATEADD() 和 DATEDIFF() 函数来获取当前月的开始和结束时间范围。以下是实现当前月时间范围查询的 SQL&#xff1a; FDATE > DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) FDATE < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) 1, 0) …

利用Java爬虫MinC根据ID获取商品详情的完整指南

在当今数字化时代&#xff0c;获取商品详情数据对于市场分析、价格监控和竞争对手分析至关重要。Java作为一种强大且广泛使用的编程语言&#xff0c;非常适合开发复杂的爬虫系统。本文将详细介绍如何利用Java编写爬虫程序来根据商品ID获取商品详情&#xff0c;并提供完整的代码…

RabbitMQ-入门

RabbitMQ-入门 基本说明 AMQP协议&#xff08;高消息队列协议&#xff1a;Advanced Message Queuing Protocol&#xff09;&#xff1a;https://www.rabbitmq.com/tutorials/amqp-concepts.html 基础组件术语 生产者&#xff08;Publisher&#xff09;&#xff1a;发消息到某…

【JAVA项目】基于ssm的【美食推荐管理系统】

【JAVA项目】基于ssm的【美食推荐管理系统】 技术简介&#xff1a;采用JSP技术、B/S架构、SSM框架、MySQL技术等实现。 系统简介&#xff1a;美食推荐管理系统&#xff0c;在系统首页可以查看首页、热门美食、美食教程、美食店铺、美食社区、美食资讯、我的、跳转到后台等内容。…

go-zero(十二)消息队列

go zero 消息队列 在微服务架构中&#xff0c;消息队列主要通过异步通信实现服务间的解耦&#xff0c;使得各个服务可以独立发展和扩展。 go-zero中使用的队列组件go-queue&#xff0c;是gozero官方实现的基于Kafka和Beanstalkd 的消息队列框架,我们使用kafka作为演示。 一、…

day30-IO-阶段综合案例(带权重的随机每日一记)(笔记完全来源于黑马程序员)

目录 0 目录一、听黑马阿玮的视频记录的笔记1. 制造假数据1.1 如何制造假数据1.2 练习1-生成方式1&#xff1a;爬取姓氏、男生名字、女生名字1.3 练习2-生成方式1&#xff1a;在练习1的基础上&#xff0c;将数据写入本地文件1.4 练习3-生成方式2&#xff1a;利用糊涂包生成假数…

Excel的文件导入遇到大文件时

Excel的文件导入向导如何把已导入数据排除 入起始行&#xff0c;选择从哪一行开始导入。 比如&#xff0c;前两行已经导入了&#xff0c;第二次导入的时候排除前两行&#xff0c;从第三行开始&#xff0c;就将导入起始行设置为3即可&#xff0c;且不勾选含标题行。 但遇到大文…