vue-router 源码分析——6.命名路由

2024-06-13 22:04

本文主要是介绍vue-router 源码分析——6.命名路由,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这是对vue-router 3 版本的源码分析。
本次分析会按以下方法进行:

  1. 按官网的使用文档顺序,围绕着某一功能点进行分析。这样不仅能学习优秀的项目源码,更能加深对项目的某个功能是如何实现的理解。这个对自己的技能提升,甚至面试时的回答都非常有帮助。
  2. 在围绕某个功能展开讲解时,所有不相干的内容都会暂时去掉,等后续涉及到对应的功能时再加上。这样最大的好处就是能循序渐进地学习,同时也不会被不相干的内容影响。省略的内容都会在代码中以…表示。
  3. 每段代码的开头都会说明它所在的文件目录,方便定位和查阅。如果一个函数内容有多个函数引用,这些都会放在同一个代码块中进行分析,不同路径的内容会在其头部加上所在的文件目录。

本章讲解router中命名路由是如何实现的。
另外我的vuex3源码分析也发布完了,欢迎大家学习:
vuex3 最全面最透彻的源码分析
还有vue-router的源码分析:
vue-router 源码分析——1. 路由匹配
vue-router 源码分析——2. router-link 组件是如何实现导航的
vue-router 源码分析——3. 动态路由匹配
vue-router 源码分析——4.嵌套路由
vue-router 源码分析——5.编程式导航

源码实现分析:

  • 官方例子
const router = new VueRouter({routes: [{path: '/user/:userId',name: 'user',component: User}]
})<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
router.push({ name: 'user', params: { userId: 123 } })
  • 回顾一下第一章,即创建vue-router 实例时内部发生了什么。router创建了一个匹配器 this.matcher,在这个内部创建了非常重要的三个数据:pathList、pathMap和nameMap。前两个之前已经介绍过了,现在介绍一下nameMap的数据结构。
  • 从下面的源码可以看出,nameMap 是以使用者定义的每个route的name(如果有)作为key,value为每个route的record。同时name也会添加到record中。
// ./create-route-map.js
export function createRouteMap(routes: Array<RouteConfig>,oldPathList?: Array<string>,oldPathMap?: Dictionary<RouteRecord>,oldNameMap?: Dictionary<RouteRecord>,parentRoute?: RouteRecord
): {pathList: Array<string>,pathMap: Dictionary<RouteRecord>,nameMap: Dictionary<RouteRecord>
} {const pathList: Array<string> = oldPathList || []const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null)const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null)reoutes.forEach(route => {addRouteRecord(pathList, pathMap, nameMap, route, parentRoute)    })...return {pathList,pathMap,nameMap    }
}function addRouteRecord (pathList: Array<string>,pathMap: Dictionary<RouteRecord>,nameMap: Dictionary<RouteRecord>,route: RouteConfig,parent?: RouteRecord,matchAs?: string
) {const { path, name } = route...const record: RouteRecord = {name,...}if (name) {if (!nameMap[name]) {nameMap[name] = record        } else if (...) {...}}
}
  • 在上一章vue-router 源码分析——5.编程式导航中已经知道在执行router.push时,调用 this.router.match 创建了一个新的路由对象(即跳转到的路由)。
// ./history/hash.js
export class HashHistory extends History {...push(location: RawLocation, onComplete?: Function, onAbort?: Function)) {...this.transitionTo(location,route => {...             }         )   }
}// ./history/base.js
export class History {...transitionTo(location: RawLocation,onComplete?: Function,onAbort?: Function) {let routetry {route = this.router.match(location, this.current) // 创建新路由}    }
}
  • 在创建新路由时,如果存在name,则通过nameMap来查找并获得相关数据(record)。
  • 通过下面的源码分析,知道了vue-router的两种匹配方式(name和path)的处理逻辑。命名路由name是使用哈希算法来进行匹配,而路径路由path是遍历数组进行匹配。在匹配时,以name匹配优先。
// ./router.js
export default class VueRoute {..match(raw: RawLocation, current?: Route, redirectedFrom?: Location): Route {return this.matcher.match(raw, current, redirectedFrom)    }
}// ./create-matcher.js
export function createMatcher {routes: Array<RouteConfig>,router: VueRouter
}: Matcher {const { pathList, pathMap, nameMap } = createRouteMap(routes)function match(raw: RawLocation,currentRoute?: Route,redirectedFrom?: Location            ): Route {const location = normalizeLocation(raw, currentRoute, false, router)const { name } = locationif (name) {const record = nameMap[name] // 通过nameMap来查找并获得record...location.path = fillParams(record.path, location.params, `named route "${name}"`)return _createRoute(record, location, redirectedFrom)} else if (location.path) {...}}
}

总结

  • 在路由初始化时,收集所有用户定义的命名路由记录到 nameMap 字典结构中。
  • 在路由匹配时,通过name作为key,从 nameMap 中取出对应的路由记录,以此来生成对应url的路由。
  • 命名路由的匹配时间复杂度要优于路径匹配(hashmap-getter 和 数组遍历),所以理论上命名路由的匹配时间要少于路径匹配。如果项目有大量路径匹配的路由时,可以转换成命名路由来优化匹配。

这篇关于vue-router 源码分析——6.命名路由的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1058549

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

变量与命名

引言         在前两个课时中,我们已经了解了 Python 程序的基本结构,学习了如何正确地使用缩进来组织代码,并且知道了注释的重要性。现在我们将进一步深入到 Python 编程的核心——变量与命名。变量是我们存储数据的主要方式,而合理的命名则有助于提高代码的可读性和可维护性。 变量的概念与使用         在 Python 中,变量是一种用来存储数据值的标识符。创建变量很简单,

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能