Vue-Router总结大全,从小白到精通,含vue3

全局解析守卫

全局后置钩子

路由独享的守卫

组件内的守卫

完整的导航解析流程

路由元信息

数据获取 数据获取 | Vue Router (vuejs.org)

导航完成后获取数据

在导航完成前获取数据

Vue Router 和 组合式 API

在 setup 中访问路由和当前路由

导航守卫

useLink

过渡动效

对所有的路由使用相同的过渡

单个路由的过渡

基于路由的动态过渡

滚动行为

延迟滚动

路由懒加载

把组件按组分块

扩展 RouterLink

检测导航故障

鉴别导航故障

检测重定向

动态路由

添加路由

删除路由

添加嵌套路由

查看现有路由


前言


这是我在实际工作中用到的先写这:

/**

  • Note: 路由配置项

  • hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1

  • alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式–如组件页面

  •                          // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
    
  •                          // 若你想不管路由下面的 children 声明的个数都显示你的根路由
    
  •                          // 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由
    
  • redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击

  • name:‘router-name’ // 设定路由的名字,一定要填写不然使用时会出现各种问题

  • meta : {

roles: [‘admin’,‘editor’] // 设置该路由进入的权限,支持多个权限叠加

title: ‘title’ // 设置该路由在侧边栏和面包屑中展示的名字

icon: ‘svg-name’ // 设置该路由的图标,对应路径src/icons/svg

breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示

}

*/

使用

通过调用 app.use(router),我们可以在任意组件中以 this. r o u t e r  的形式访问它,并且以  t h i s . router 的形式访问它,并且以 this. router 的形式访问它,并且以 this.route 的形式访问当前路由:

// 5. 创建并挂载根实例

const app = Vue.createApp({})

//确保 use 路由实例使

//整个应用支持路由。

app.use(router)

app.mount(‘#app’)

要在 setup 函数中访问路由,请调用 useRouter 或 useRoute 函数

/users/johnny 和 /users/jolyne 这样的 URL 都会映射到同一个路由。

// 这些都会传递给 createRouter

const routes = [

// 动态段以冒号开始

{ path: ‘/users/:id’, component: User },

]

路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来。因此,我们可以通过更新 User 的模板来呈现当前的用户 ID:

用户从 /users/johnny 导航到 /users/jolyne 时,相同的组件实例将被重复使用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会被调用。

捕获所有路由或 404 Not found 路由

想匹配任意路径,我们可以使用自定义的 路径参数 正则表达式,在 路径参数 后面的括号中加入 正则表达式 :

const routes = [

// 将匹配所有内容并将其放在 $route.params.pathMatch

{ path: ‘/:pathMatch(.)’, name: ‘NotFound’, component: NotFound },

// 将匹配以 /user- 开头的所有内容,并将其放在 $route.params.afterUser

{ path: ‘/user-:afterUser(.*)’, component: UserGeneric },

]

当你访问 /user/eduardo 时,在 User 的 router-view 里面什么都不会呈现,因为没有匹配到嵌套路由。也许你确实想在那里渲染一些东西。在这种情况下,你可以提供一个空的嵌套路径:

const routes = [

{

path: ‘/user/:id’,

component: User,

children: [

// when /user/:id is matched

// 当 /user/:id 匹配成功

// UserHome 将被直接渲染到 User 的 内部

{ path: ‘’, component: UserHome },

// …其他子路由

],

},

]

编程式导航


点击  时,内部会调用这个方法,所以点击  相当于调用 router.push(…) :

声明式

编程式

<router-link :to="...">

router.push(...)

替换当前位置

它的作用类似于 router.push,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。

声明式

编程式

<router-link :to="..." replace>

router.replace(...)

该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 window.history.go(n)。

// 向前移动一条记录,与 router.forward() 相同

router.go(1)

// 返回一条记录,与router.back() 相同

router.go(-1)

// 前进 3 条记录

router.go(3)

// 如果没有那么多记录,静默失败

router.go(-100)

router.go(100)

router.push、router.replace 和 router.go 是 window.history.pushState、window.history.replaceState 和 window.history.go 的翻版,它们确实模仿了 window.history 的 API。

值得一提的是,无论在创建路由器实例时传递什么样的history 配置,Vue Router 的导航方法(push、replace、go)都能始终如一地工作。

命名视图


有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。

别名


通过别名,你可以自由地将 UI 结构映射到一个任意的 URL,而不受配置的嵌套结构的限制。

路由组件传参


布尔模式

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

const User = {

template: ‘

User {{ $route.params.id }}

}

const routes = [{ path: ‘/user/:id’, component: User }]

//改为

const User = {

props: [‘id’],

template: ‘

User {{ id }}

}

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

不同的历史记录模式


history 配置允许我们在不同的历史模式中进行选择。

hash 模式

import { createRouter, createWebHashHistory } from ‘vue-router’

const router = createRouter({

history: createWebHashHistory(),

routes: [

//…

],

})

它在内部传递的实际 URL 之前使用了一个哈希字符(#)。它在 SEO 中确实有不好的影响

HTML5 模式

用 createWebHistory() 创建 HTML5 模式,推荐使用这个模式:

不带#号,

不过,问题来了。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问 https://example.com/user/id,就会得到一个 404 错误。这就丑了。

要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html 相同的页面。漂亮依旧!

不同的历史模式 | Vue Router (vuejs.org)")

导航守卫


vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。

全局前置守卫

router.beforeEach 注册一个全局前置守卫:

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。

每个守卫方法接收两个参数:

  • to: 即将要进入的目标

  • from: 当前导航正要离开的路由

可以返回return的值如下:

  • false: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。

  • 一个路由地址: 通过一个路由地址跳转到一个不同的地址,就像你调用 router.push()") 一样,你可以设置诸如 replace: true 或 name: ‘home’ 之类的配置。当前的导航被中断,然后进行一个新的导航,就和 from 一样。

如果遇到了意料之外的情况,可能会抛出一个 Error。这会取消导航并且调

用 router.onError()") 注册过的回调。

如果什么都没有,undefined 或返回 true,则导航是有效的,并调用下一个导航守卫

全局解析守卫

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

router.beforeResolve 是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。

全局后置钩子

router.afterEach

和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。

路由独享的守卫

可以直接在路由配置上定义 beforeEnter 守卫:

beforeEnter 守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发。

const routes = [

{

path: ‘/users/:id’,

component: UserDetails,

beforeEnter: (to, from) => {

// reject the navigation

return false

},

},

]

你也可以将一个函数数组传递给 beforeEnter,这在为不同的路由重用守卫时很有用:

组件内的守卫

你可以在路由组件内直接定义路由导航守卫(传递给路由配置的)

可用的配置 API

你可以为路由组件添加以下配置:

  • beforeRouteEnter

  • beforeRouteUpdate

  • beforeRouteLeave

const UserDetails = {

template: ...,

beforeRouteEnter(to, from) {

// 在渲染该组件的对应路由被验证前调用

// 不能获取组件实例 this

// 因为当守卫执行时,组件实例还没被创建!

},

beforeRouteUpdate(to, from) {

// 在当前路由改变,但是该组件被复用时调用

// 举例来说,对于一个带有动态参数的路径 /users/:id,在 /users/1/users/2 之间跳转的时候,

// 由于会渲染同样的 UserDetails 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。

// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 this

},

beforeRouteLeave(to, from) {

// 在导航离开渲染该组件的对应路由时调用

// 与 beforeRouteUpdate 一样,它可以访问组件实例 this

},

}

beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。

不过,你可以通过传一个回调给 next 来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数:

beforeRouteEnter (to, from, next) {

next(vm => {

// 通过 vm 访问组件实例

})

}

这个 离开守卫 通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回 false 来取消。

beforeRouteLeave (to, from) {

const answer = window.confirm(‘Do you really want to leave? you have unsaved changes!’)

if (!answer) return false

}

完整的导航解析流程

  1. 导航被触发。

  2. 在失活的组件里调用 beforeRouteLeave 守卫。

  3. 调用全局的 beforeEach 守卫。

  4. 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。

  5. 在路由配置里调用 beforeEnter。

  6. 解析异步路由组件。

  7. 在被激活的组件里调用 beforeRouteEnter。

  8. 调用全局的 beforeResolve 守卫(2.5+)。

  9. 导航被确认。

  10. 调用全局的 afterEach 钩子。

  11. 触发 DOM 更新。

  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

路由元信息


有时,你可能希望将任意信息附加到路由上,如过渡名称、谁可以访问路由等。这些事情可以通过接收属性对象的meta属性来实现,并且它可以在路由地址和导航守卫上都被访问到。

const routes = [

{

path: ‘/posts’,

component: PostsLayout,

children: [

{

path: ‘new’,

component: PostsNew,

// 只有经过身份验证的用户才能创建帖子

meta: { requiresAuth: true }

},

{

path: ‘:id’,

component: PostsDetail

// 任何人都可以阅读文章

meta: { requiresAuth: false }

}

]

}

]

我们称呼 routes 配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,它可能匹配多个路由记录。

一个路由匹配到的所有路由记录会暴露为  r o u t e  对象 ( 还有在导航守卫中的路由对象 ) 的 route 对象(还有在导航守卫中的路由对象)的 route 对象(还有在导航守卫中的路由对象)route.matched 数组。

我们需要遍历这个数组来检查路由记录中的 meta 字段,但是 Vue Router 还为你提供了一个 $route.meta 方法,它是一个非递归合并所有 meta 字段的(从父字段到子字段)的方法。这意味着你可以简单地写

router.beforeEach((to, from) => {

// 而不是去检查每条路由记录

// to.matched.some(record => record.meta.requiresAuth)

if (to.meta.requiresAuth && !auth.isLoggedIn()) {

// 此路由需要授权,请检查是否已登录

// 如果没有,则重定向到登录页面

return {

path: ‘/login’,

// 保存我们所在的位置,以便以后再来

query: { redirect: to.fullPath },

}

}

})

TypeScript

可以通过扩展 RouteMeta 接口来输入 meta 字段:

// typings.d.ts or router.ts

import ‘vue-router’

declare module ‘vue-router’ {

interface RouteMeta {

// 是可选的

isAdmin?: boolean

// 每个路由都必须声明

requiresAuth: boolean

}

}

数据获取 数据获取 | Vue Router (vuejs.org)")


有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。我们可以通过两种方式来实现:

  • 导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。

  • 导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。

从技术角度讲,两种方式都不错 —— 就看你想要的用户体验是哪种。

导航完成后获取数据

当你使用这种方式时,我们会马上导航和渲染组件,然后在组件的 created 钩子中获取数据。这让我们有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。

在导航完成前获取数据

通过这种方式,我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 守卫中获取数据,当数据获取成功后只调用 next 方法:

在为后面的视图获取数据时,用户会停留在当前的界面,因此建议在数据获取期间,显示一些进度条或者别的指示。如果数据获取失败,同样有必要展示一些全局的错误提醒。

Vue Router 和 组合式 API


在 setup 中访问路由和当前路由

route 对象是一个响应式对象,所以它的任何属性都可以被监听,但你应该避免监听整个 route 对象:

因为我们在 setup 里面没有访问 this,所以我们不能再直接访问 this. r o u t e r  或  t h i s . router 或 this. router  this.route。作为替代,我们使用 useRouter 函数:

请注意,在模板中我们仍然可以访问  r o u t e r  和  router 和  router  route,所以不需要在 setup 中返回 router 或 route。

导航守卫

虽然你仍然可以通过 setup 函数来使用组件内的导航守卫,但 Vue Router 将更新和离开守卫作为 组合式 API 函数公开:

import { onBeforeRouteLeave, onBeforeRouteUpdate } from ‘vue-router’

export default {

setup() {

// 与 beforeRouteLeave 相同,无法访问 this

onBeforeRouteLeave((to, from) => {

const answer = window.confirm(

‘Do you really want to leave? you have unsaved changes!’

)

// 取消导航并停留在同一页面上

if (!answer) return false

})

const userData = ref()

// 与 beforeRouteLeave 相同,无法访问 this

onBeforeRouteUpdate(async (to, from) => {

//仅当 id 更改时才获取用户,例如仅 query 或 hash 值已更改

if (to.params.id !== from.params.id) {

userData.value = await fetchUser(to.params.id)

}

})

},

}

组合式 API 守卫也可以用在任何由  渲染的组件中,它们不必像组件内守卫那样直接用在路由组件上。

useLink

Vue Router 将 RouterLink 的内部行为作为一个组合式 API 函数公开。它提供了与 v-slot API 相同的访问属性:

过渡动效


想要在你的路径组件上使用转场,并对导航进行动画处理,你需要使用 v-slot API

对所有的路由使用相同的过渡

//把原来这个路由视图换成这个加动画的试图即可

单个路由的过渡

想让每个路由的组件有不同的过渡,你可以将元信息和动态的 name 结合在一起,放在 上:

const routes = [

{

path: ‘/custom-transition’,

component: PanelLeft,

meta: { transition: ‘slide-left’ },

},

{

path: ‘/other-transition’,

component: PanelRight,

meta: { transition: ‘slide-right’ },

},

]

基于路由的动态过渡

也可以根据目标路由和当前路由之间的关系,动态地确定使用的过渡。使用和刚才非常相似的片段:

我们可以添加一个 after navigation hook (后置钩子),根据路径的深度动态添加信息到 meta 字段。

router.afterEach((to, from) => {

const toDepth = to.path.split(‘/’).length

const fromDepth = from.path.split(‘/’).length

to.meta.transitionName = toDepth < fromDepth ? ‘slide-right’ : ‘slide-left’

})

滚动行为


使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。

注意: 这个功能只在支持 history.pushState 的浏览器中可用。

当创建一个 Router 实例,你可以提供一个 scrollBehavior 方法:

const router = createRouter({

history: createWebHashHistory(),

routes: […],

scrollBehavior (to, from, savedPosition) {

// return 期望滚动到哪个的位置

}

})

scrollBehavior 函数接收 to和 from 路由对象,如 Navigation Guards。第三个参数 savedPosition,只有当这是一个 popstate 导航时才可用(由浏览器的后退/前进按钮触发)。

该函数可以返回一个 ScrollToOptions 位置对象:

const router = createRouter({

scrollBehavior(to, from, savedPosition) {

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。

注意: 这个功能只在支持 history.pushState 的浏览器中可用。

当创建一个 Router 实例,你可以提供一个 scrollBehavior 方法:

const router = createRouter({

history: createWebHashHistory(),

routes: […],

scrollBehavior (to, from, savedPosition) {

// return 期望滚动到哪个的位置

}

})

scrollBehavior 函数接收 to和 from 路由对象,如 Navigation Guards。第三个参数 savedPosition,只有当这是一个 popstate 导航时才可用(由浏览器的后退/前进按钮触发)。

该函数可以返回一个 ScrollToOptions 位置对象:

const router = createRouter({

scrollBehavior(to, from, savedPosition) {

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-CIjPKT0t-1715658922261)]

[外链图片转存中…(img-L48qpUPp-1715658922262)]

[外链图片转存中…(img-ZuhgfrbS-1715658922262)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值