vue-router3 源码注释系列 /src/util/push-state.js

颛孙玉石
2023-12-01
/* @flow */

//用于判断是否是浏览器环境
import { inBrowser } from './dom'
//保存滚动的位置(x,y).
import { saveScrollPosition } from './scroll'
// genStateKey 生成基于当前时间时间戳的key。
// setStateKey 更新key。
// getStateKey 获取key。
import { genStateKey, setStateKey, getStateKey } from './state-key'
// extend(a, b) 将 b 对象中属性浅拷贝到 a 对象中。
import { extend } from './misc'

/*
  判断浏览器是否支持 history 模式。
*/
export const supportsPushState =
  //inBrowser 是否是浏览器环境。
  inBrowser &&
  (function () {
    //获取用户代理对象。
    const ua = window.navigator.userAgent

    //满足下面条件的 ua,则不支持 html5 的导航模式。
    if (
      (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
      ua.indexOf('Mobile Safari') !== -1 &&
      ua.indexOf('Chrome') === -1 &&
      ua.indexOf('Windows Phone') === -1
    ) {
      return false
    }

    //判断window 是否存在 history对象,且 pushState 方法是否存在。
    //如果都存在,则表明支持 html5 的导航模式。
    return window.history && typeof window.history.pushState === 'function'
  })()

/*
  push 方式跳转新路径,会在 history 中记录。
*/
export function pushState(url?: string, replace?: boolean) {
  //保存当前页面滚动的位置。
  saveScrollPosition()

  // try...catch the pushState call to get around Safari
  // DOM Exception 18 where it limits to 100 pushState calls
  //获取导航对象
  const history = window.history
  try {
    if (replace) {
      //保存之前 history 的 state。
      // preserve existing history state as it could be overriden by the user
      const stateCopy = extend({}, history.state)
      stateCopy.key = getStateKey()
      //使用 history 的 replace 方法。
      // 第一个参数是 state.  这里就是 { key: “当前时间的时间戳字符串”  }
      // 第二个参数是 title, 这个值没有意义了。
      // 第三个参数是  url, 要跳转的url。
      history.replaceState(stateCopy, '', url)
    } else {
      //使用 history 的 push 方法。
      // 第一个参数是 state
      // 第二个参数是 title
      // 第三个参数是  url
      history.pushState({ key: setStateKey(genStateKey()) }, '', url)
    }
  } catch (e) {
    //如果抛出了异常,则表示栈已经到了最大值,不能push了。
    //使用 location.assign 也可以用来跳转网址,且 assign 会添加记录到浏览历史,点击后退可以返回到之前页面。
    window.location[replace ? 'replace' : 'assign'](url)
  }
}

/*
  replace 方式跳转新路径,不会在 history 中记录。
*/
export function replaceState(url?: string) {
  //第二个参数是 true,表示以 replace 的方式去跳转到新页面。
  pushState(url, true)
}

 类似资料: