vue-router 源码分析——8.重定向

这是对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.编程式导航
vue-router 源码分析——6.命名路由
vue-router 源码分析——7.命名视图

官方示例:

  • 重定向是通过 routes 配置来完成,重定向的目标也可以是一个命名路由,或者一个方法。
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' },
    { path: '/b', component: b_component} // 重定向的路由必须在router中定义
  ]
})

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 方法接收 目标路由 作为参数
      // return 重定向的 字符串路径/路径对象
    }}
  ]
})

Router初始化:

  • Router初始化生成匹配器和路由记录表,redirect属性会被复制到路由的路由记录上:
// router.js
import type { Matcher } from './create-matcher'
export default class VueRouter {
    ...
    constructor(options: RouterOptions = {}) {
        ...
        this.matcher = createMatcher(options.routes || [], this)
    }
}

// ./create-matcher.js
import { createRouteMap } from './create-route-map'
export function createMatcher(
    routes: Array<RouteConfig>,
    router: VueRouter
): Matcher {
    const { pathList, pathMap, nameMap } = createRouteMap(routes)
    ...
}

// ./create-route-map/js
export function createRouteMap(
    routes: Array<RouteConfig>,
    ...
): {
    pathList: Array<string>,
    pathMap: Dictionary<RouteRecord>,
    nameMap: Dictionary<RouteRecord>
} {
    const pathList: Array<string> =  []
    const pathMap: Dictionary<RouteRecord> = Object.create(null)
    const nameMap: Dictionary<RouteRecord> = Object.create(null)
    routes.forEach(route => {
        addRouteRecord(pathList, pathMap, nameMap, route, parentRoute)
    })
    ...
}

function addRouteRecord(
    pathList: Array<string>,
    pathMap: Dictionary<RouteRecord>,
    nameMap: Dictionary<RouteRecord>,
    route: RouteConfig,
    parent?: RouteRecord,
    matchAs?: string
) {
    ...
    const record: RouteRecord = {
        redirect: route.redirect,
        ...    
    }
}

触发逻辑:

  • 当试图跳转到url ‘/a’ 时,会触发路由匹配。
  • 首先匹配到路由路径为’/a’的路由记录,然后判断它是否有redirect属性,如果有就执行redirect函数。
  • 接着在redirect函数中取出redirect内容,对其进行了结构类型统一化。这里就解释了为什么配置重定向的目标可以是字符串形式的path,或者命名路由,或者方法。
  • 最后,构建了一个基于redirect目标的数据,作为参数传入match函数进行路由匹配。这样的递归调用也能解决多重的重定向。
// 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 } = location
        if (name) {
            // 基于命名路由的匹配逻辑        
        } else if (location.path) {
              location.params = {}
              for (let i = 0; i < pathList.length; i++) {
                  const path = pathList[i]
                  const record = pathMap[path]
                  if (matchRoute(record.regex, location.path, location.params)) {
                      // 这里匹配到路由'/a'的相关记录后,执行创建路由的操作
                      return _createRoute(record, location, redirectedFrom)
                  }
              }      
        }
    }
    function _createRoute(
        record: ?RouteRecord,
        location: Location,
        redirectedFrom?: Location    
    ): Route {
        // 如果当前的路由记录有重定向,就执行重定向的相关逻辑,否则创建'/a'的路由内容
        if (record && record.redirect) {
            return redirect(record, redirectedFrom || location)        
        }
        ...
        return createRoute(record, location, redirectedFrom, router)
    }
    function redirect(
        record: RouteRecord,
        location: Location
    ): Route {
    	const originalRedirect = record.redirect
        // 下面这段代码解释了为什么重定向可以是一个方法,同时接受的参数是目标路由,
        let redirect = typeof originalRedirect === 'function'
            ? originalRedirect(createRoute(record, location, null, router))
            : originalRedirect
        // 最后无论重定向设置的是字符串,命名路由,方法,都会统一成一个对象结构
        if (typeof redirect === 'string') {
            redirect = {path = redirect}        
        }
        ...
        const re: Object = redirect
        const { name, path } = re
        ...
        if (name) {
            const targetRecord = nameMap[name]
            ...
            return match({
                name,
                ...            
            }, undefined, location)       
        } else if (path) {
        	const rawPath = resolveRecordPath(path, record) 
            const resolvedPath = fillParams(rawPath, params, `redirect route with path "${rawPath}"`)
            return match({
                path: resolvedPath, // 官网示例中定义的重定向都不复杂,这里的path = '/b'没有任何改变
                ...          
            }, undefined, location)       
        }
    }
}

细节补充:

  • 当重定向完成,匹配路由成功后,调用createRoute函数生成匹配路由时,增加了一个redirectedFrom属性,记录的是它的重定向的源路径。这样可以方便用户查看或者执行其他功能。
// ./util/route.js
export function createRoute(
    record: ?RouteRecord,
    location: Location,
    redirectedFrom?: ?Location,
    router?: VueRouter
): Route {
    ...
    const route: Route = {
        ...  
    }
    if (redirectedFrom) {
        route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery)            
    }
    return Object.freeze(route)
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

.net core 的 winform 的 浏览器控件 WebView2

在.NET Core WinForms应用程序中&#xff0c;没有直接的“浏览器控件”&#xff0c;因为WinForms不支持像WebBrowser控件那样的功能。但是&#xff0c;你可以使用WebView2控件&#xff0c;它是一个基于Chromium的浏览器内核&#xff0c;可以在WinForms应用程序中嵌入Web内容。 …

Science Robotics 麻省理工学院最新研究,从仿真中学习的精确选择、定位和抓放物体的视触觉方法

现有的机器人系统在通用性和精确性两个性能目标上难以同时兼顾&#xff0c;往往会陷入一个机器人解决单个任务的情况&#xff0c;缺乏"精确泛化"。本文针对精准和通用的同时兼顾提出了解决方法。提出了SimPLE(Pick Localize和placE的仿真模拟)作为精确拾取和放置的解…

昇思25天学习打卡营第9天|MindSpore使用静态图加速(基于context的开启方式)

在Graph模式下&#xff0c;Python代码并不是由Python解释器去执行&#xff0c;而是将代码编译成静态计算图&#xff0c;然后执行静态计算图。 在静态图模式下&#xff0c;MindSpore通过源码转换的方式&#xff0c;将Python的源码转换成中间表达IR&#xff08;Intermediate Repr…

电气-伺服(6)脉冲控制

一、脉冲模式原理&#xff1a; 运动控制器输出脉冲信号给伺服驱动器 伺服驱动器工作于位置模式 伺服驱动器内部要完成三闭环&#xff08;位置闭环 、速度闭环、电流环&#xff09; 脉冲和伺服控制环&#xff1a;脉冲的个数作用于位置环。脉冲的频率作用于速度环 二、脉冲的两…

ATFX汇市:美国大非农数据来袭,美指与欧元或迎剧烈波动

ATFX汇市&#xff1a;今日20:30&#xff0c;美国劳工部将公布6月非农就业报告&#xff0c;其中新增非农就业人口数据最受关注&#xff0c;前值为27.2万人&#xff0c;预期值19万人&#xff0c;预期降幅高达8.2万人。如果公布值确实如预期一般&#xff0c;美联储降息预期将增强&…

mysql 字符集(character set)和排序规则(collation)

文章目录 概念1、字符集1.1、举例1.2、常见字符集 utf8 和 utf8mb4 区别1.3、字符集 使用 2、排序规则2.1、举例2.2、常见的排序规则 utf8mb4_bin 、utf8mb4_general_ci、utf8mb4_unicode_ci2.3、使用 概念 在 MySQL 中&#xff0c;字符集&#xff08;character set&#xff0…

昇思25天学习打卡营第8天|ResNet50迁移学习

一、迁移学习定义 迁移学习&#xff08;Transfer Learning&#xff09;&#xff1a;在一个任务上训练得到的模型包含的知识可以部分或全部地转移到另一个任务上。允许模型将从一个任务中学到的知识应用到另一个相关的任务中。适用于数据稀缺的情况&#xff0c;可减少对大量标记…

【代码大全2 选读】看看骨灰级高手消灭 if-else 逻辑的瑞士军刀长啥样

文章目录 1 【写在前面】2 【心法】这把瑞士军刀长啥样3 【示例1】确定某个月份的天数&#xff08;Days-in-Month Example&#xff09;4 【示例2】确定保险费率&#xff08;Insurance Rates Example&#xff09;5 【示例3】灵活的消息格式&#xff08;Flexible-Message-Format …

Windows10删除文件有较长延误的修复方法

Windows10删除文件有较长延误的修复方法 问题描述处理方法 问题描述 电脑配置很好&#xff0c;但是执行文件等删除操作时很长时间才有反应&#xff0c;才会弹出是否删除对话框。或者将文件移动到回收站&#xff0c;也是同样如此。 处理方法 第一步&#xff1a;以管理员身份启…

gitLab使用流程

标题1.配置账户 git config --global user.name git config --global user.email mygitlabmali.cn 标题2.生成秘匙 ssh-keygen -t rsa -C “mygitlabmail.cn” 。 //输入命令后一直回车 &#xff0c;输入命令后一直回车&#xff08;密码可以不填&#xff09;&#xff0c;至…

国际上备考所有AWS云计算/IT证书的五大优质免费课程网站

最近越来越多的小伙伴来问小李哥&#xff0c;小李哥亚马逊云科技AWS认证大满贯是在哪里上课复习的呢&#xff1f;全部上付费课程那不是一笔巨款吗&#xff1f;小李哥这次来盘点备考国际上IT证书的5大优质免费课程网站(不只是亚马逊云科技AWS的课程&#xff0c;其他课程同样可以…

Jemeter--独立变参接口压测

Jemeter–独立不变参接口压测 Jemeter–独立变参接口压测 Jemeter–关联接口压测 从数据库获取变参数据源 1、压测计划处添加对应数据库驱动包 左键点击压测计划&#xff0c;进入压测计划页面&#xff0c;点击浏览添加数据库链接jar包 2、线程组添加 JDBC配置原件 填写数据…

技术驱动:探索SpringBoot的大文件上传策略

1.分片上传技术 为了处理大文件上传并保证性能&#xff0c;前后端可以使用分片上传&#xff08;也称为分块上传&#xff09;技术。 1.选择原因 分片上传&#xff08;也称为分块上传&#xff09;是一种处理大文件上传的技术&#xff0c;主要目的是提高上传的可靠性和效率。 网…

用requirements.txt配置环境

1. 在anaconda创建环境 创建Python版本为3.8的环境&#xff0c;与yolov5所需的包适配。 2. 在Anaconda Prompt中激活环境 (base) C:\Users\吴伊晴>conda activate yolov5 3. 配置环境 用指定路径中的requirements.txt配置环境。 (yolov5) C:\Users\吴伊晴>pip insta…

LeetCode热题100刷题4:76. 最小覆盖子串、239. 滑动窗口最大值、53. 最大子数组和、56. 合并区间

76. 最小覆盖子串 滑动窗口解决字串问题。 labuladong的算法小抄中关于滑动窗口的算法总结&#xff1a; class Solution { public:string minWindow(string s, string t) {unordered_map<char,int> need,window;for(char c : t) {need[c];}int left 0, right 0;int …

【手机取证】如何使用360加固助手给apk加固

文章关键词&#xff1a;手机取证、电子数据取证、数据恢复 一、前言 APP加固是对APP代码逻辑的一种保护。原理是将应用文件进行某种形式的转换&#xff0c;包括不限于隐藏&#xff0c;混淆&#xff0c;加密等操作&#xff0c;进一步保护软件的利益不受损坏&#xff0c;下面给…

Java并发编程知识整理笔记

目录 ​1. 什么是线程和进程&#xff1f; 线程与进程有什么区别&#xff1f; 那什么是上下文切换&#xff1f; 进程间怎么通信&#xff1f; 什么是用户线程和守护线程&#xff1f; 2. 并行和并发的区别&#xff1f; 3. 创建线程的几种方式&#xff1f; Runnable接口和C…

pycharm如何使用jupyter

目录 配置jupyter新建jupyter文件别人写的方法&#xff08;在pycharm种安装&#xff0c;在网页中使用&#xff09; pycharm专业版 配置jupyter 在pycharm终端启动一个conda虚拟环境&#xff0c;输入 conda install jupyter会有很多前置包需要安装&#xff1a; 新建jupyter…

中国IDC圈探访北京•光子1号金融算力中心

今天&#xff0c;“AI”、“大模型”是最炙手可热的话题&#xff0c;全球有海量人群在工作生活中使用大模型&#xff0c;大模型产品涉及多模态&#xff0c;应用范围已涵盖电商、传媒、金融、短视频、制造等众多行业。 而回看2003年的互联网记忆&#xff0c; “上网”“在线”是…

空状态页面设计的艺术与科学

空状态界面是用户在网站、APP中遇到的因无数据展示而中断体验的界面&#xff0c;这个界面设计对于解决用户疑惑有着很大的帮助。那么我们应该如何设计空状态界面呢&#xff1f;空状态是指在界面设计中&#xff0c;没有内容或数据时所显示的状态。它可能出现在各种情况下&#x…