【vue-router源码】二、createWebHistory、createWebHashHistory、createMemoryHistory源码解析

【vue-rouer源码】系列文章

  1. 【vue-router源码】一、router.install解析
  2. 【vue-router源码】二、createWebHistory、createWebHashHistory、createMemoryHistory源码解析
  3. 【vue-router源码】三、理解Vue-router中的Matcher
  4. 【vue-router源码】四、createRouter源码解析
  5. 【vue-router源码】五、router.addRoute、router.removeRoute、router.hasRoute、router.getRoutes源码分析
  6. 【vue-router源码】六、router.resolve源码解析
  7. 【vue-router源码】七、router.push、router.replace源码解析
  8. 【vue-router源码】八、router.go、router.back、router.forward源码解析
  9. 【vue-router源码】九、全局导航守卫的实现
  10. 【vue-router源码】十、isReady源码解析
  11. 【vue-router源码】十一、onBeforeRouteLeave、onBeforeRouteUpdate源码分析
  12. 【vue-router源码】十二、useRoute、useRouter、useLink源码分析
  13. 【vue-router源码】十三、RouterLink源码分析
  14. 【vue-router源码】十四、RouterView源码分析


前言

【vue-router源码】系列文章将带你从0开始了解vue-router的具体实现。该系列文章源码参考vue-router v4.0.15
源码地址:https://github.com/vuejs/router
阅读该文章的前提是你最好了解vue-router的基本使用,如果你没有使用过的话,可通过vue-router官网学习下。

vue-router 4.x中创建router时,需要使用createWebHistorycreateWebHashHistorycreateMemoryHistory中的一个创建一个history,这篇文章将就这三个函数进行解析。

使用

import {
    createWebHistory, createRouter } from 'vue-router'

const routerHistory = createWebHistory()

const router = createRouter({
   
	history: routerHistory,
	routes: [ ... ]
})

createWebHistory

createWebHistory源码所处位置:src/history/html5.ts
首先来看createWebHistory的参数,函数可以接受一个base字符串可选参数,该参数提供了一个基础路径。
createWebHistory中首先会调用normalizeBase函数对传入的base进行标准化。

base = normalizeBase(base)

来看下base标准化的过程:

export function normalizeBase(base?: string): string {
   
  if (!base) {
   
  	// 浏览其环境下尝试获取base标签的href属性
    if (isBrowser) {
   
      const baseEl = document.querySelector('base')
      base = (baseEl && baseEl.getAttribute('href')) || '/'
      // 去除htttp(s)://xxx/,如https://example.com/folder/ --> /folder/
      base = base.replace(/^\w+:\/\/[^\/]+/, '')
    } else {
   
      base = '/'
    }
  }
  // 确保base的前导/
  if (base[0] !== '/' && base[0] !== '#') base = '/' + base

  return removeTrailingSlash(base)
}

如果没有配置base的话,在浏览器环境下会尝试获取<base>标签的href属性作为base,如果没有<base>标签或<base>标签的href属性没有值,base/,然后又对base进行了reaplce(/^\w+:\/\/[^\/]+/, '')操作,该操作是去除basehttp(s)://xxx部分(如果basehttps://example.com/floder/childbase最终会变成/floder/child);非浏览器环境下,base直接取/。在最后会将base的末尾/去除,然后返回base,这样做的目的是后续我们可以通过base + fullPath的形式建立一个href

base标准化后,会声明一个historyNavigationhistoryListeners变量:

const historyNavigation = useHistoryStateNavigation(base)
const historyListeners = useHistoryListeners(
  base,
  historyNavigation.state,
  historyNavigation.location,
  historyNavigation.replace
)

这两个变量是什么呢?接下来看下useHistoryStateNavigation()useHistoryListeners()的实现。

先看useHistoryStateNavigation:

function useHistoryStateNavigation(base: string) {
   
  // 获取window.history、window.location
  const {
    history, location } = window

  const currentLocation: ValueContainer<HistoryLocation> = {
   
    value: createCurrentLocation(base, location),
  }
  const historyState: ValueContainer<StateEntry> = {
    value:  }
  // 如果history.state是空的,构建一条新的历史记录
  if (!historyState.value) {
   
    changeLocation(
      currentLocation.value,
      {
   
        back: null,
        current: currentLocation.value,
        forward: null,
        position: history.length - 1,
        replaced: true,
        scroll: null,
      },
      true
    )
  }
  // 修改历史记录
  function changeLocation(
    to: HistoryLocation,
    state: StateEntry,
    replace: boolean
  ): void {
   
    const hashIndex = base.indexOf('#')
    // 获取url,作为history.replaceState/pushState的参数
    // 如果hashIndex > -1,url = `{location.host && document.querySelector('base') ? base : base字符串#及后面字符}${to}`
    // 否则 url = `${location.protocol}//${location.host}${base}${to}`
    co
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MAXLZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值