首页 > 编程语言 >vue-router 源码分析——8.重定向

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

时间:2024-07-05 20:29:29浏览次数:14  
标签:redirect ... vue const 源码 path router 路由

这是对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)
}

标签:redirect,...,vue,const,源码,path,router,路由
From: https://blog.csdn.net/miyagiSimple/article/details/140217353

相关文章

  • SIFT源码分析
            SIFT的原理以及逻辑过程我就不细说了,网上有很多的教程大家可以参考,今天我主要是对SIFT的源码进行细致的分析,包括代码中的各种细节也都会一一讲解。        我是先贴代码然后做解释std::unique_ptr<Regions>Describe(constimage::Image<unsi......
  • windows server + iis 部署若伊前端vue项目
    一、背景说明工作原因,一直使用若伊前后端分离版框架进行二次开发。客户的服务器多数为windowsserver系统,少部分为linux系统。过去一直是使用nginx进行前端的部署,nginx的代理功能确实强大,但是在windows系统上发现一些小问题。前阵子机缘巧合之下发现了Windowsserver操作系统自带......
  • Vue 快速入门案例
    步骤一:引入vue.js文件添加<script>标签并标明路径步骤二:定义Vue对象el    Vue接管区域data    定义数据模型步骤三:编写视图层的展示v-model    绑定数据模型{{要展示的数据模型}}运行效果总结文本框里的值(左hello)修改,展示的值(右hel......
  • Vue-cli
    环境准备nodejs安装验证nodejs环境变量配置npm的全局安装路径切换npm的淘宝镜像安装Vue-clinode-v//验证是否安装成功安装成功会显示版本回头再写...验证是否安装成功vue--version安装成功会显示版本  创建Vue项目vueui点击创建 可以看到进......
  • 初学vue3, 全是黑盒子,vue3知识点汇总
    学习Vue.js应该像学习一门编程语言一样,首先要熟练掌握常用的知识,而对于不常用的内容可以简单了解一下。先对整个框架和语言有一个大致的轮廓,然后再逐步补充细节。千万不要像学习算法那样,一开始就钻牛角尖。前序:vueAPI的风格分为:选项式和组合式,vue2中一般用选项式,所......
  • SpringCloud Alibaba Nacos 配置动态更新源码学习总结(二)
    书接上回SpringCloudAlibabaNacos配置动态更新源码学习总结主要看了SpringCloudAlibabNacos的动态配置原理,依赖于部分的springcloud的组件,比如org.springframework.cloud.bootstrap.BootstrapConfiguration,在启动之前进行干预项目启动,那么在之前springboot项目怎么实现的......
  • Vue 与 scoped
    在Vue中,scoped是一个用于<style>标签的特殊属性,它的作用是将样式限定在当前组件的范围内,避免样式污染其他组件。这对于大型项目尤其有用,因为它可以确保组件的样式是独立的,不会意外地影响到其他组件。使用scoped在Vue组件中,你可以通过在<style>标签上添加scoped属性......
  • Ant Design Vue文字溢出鼠标滑上显示tooltip。不溢出,鼠标滑上不显示tooltip,溢出显示to
    <templateslot="testContent"slot-scope="{record}"><a-tooltip@mouseenter="showToolTip"overlayClassName="customtooltip_class"......
  • ArrayList底层结构和源码分析
    //无参构造器创建ArrayList对象//ArrayListlist=newArrayList();//断点1ArrayListlist=newArrayList(8);//断点2//添加1-10数据for(inti=0;i<=10;i++){list.add(i);}//添......
  • 博客屋网址导航自适应主题php源码
    博客屋网址导航自适应主题php源码v1.0是一个以PHP+MySQL进行开发的网址导航源码。模板源码后台开源无加密,可二次开发,前端响应式自适应多端屏幕。主题源码适合个人建站技术,个人博客论坛,个人日记分享等个人网站内容。站长也可以修改成其他行业的内容目录导航。演示地址http://cn......