Vue【vue-router底层实现原理】

本文详细解析了VueRouter3.0和4.0中history和hash模式的实现原理,包括如何通过封装window.history对象和监听popstate/hashchange事件来控制页面渲染。着重介绍了在不同版本中如何处理浏览器前进后退操作保持页面同步。


前言

vue-router是vue的官方路由库,它提供了两种路由模式history和hash。分别有着不同的实现原理,并且在3版本和4版本对hash模式的实现也是不同的。


一、history模式实现原理

vue-router3.0版本和4.0版本下history模式的实现原理都是通过封装window.history对象来实现。
大致流程就是

  • 封装history
    vue-router通过封装history的方法(pushState、replaceSatte)等方法,使的我们在调用vue-router上方法(push等)时能够做到两件事。
    1. 使得命中的路由组件渲染或销毁
    2. 同步浏览器的页面栈数据,当页面重新刷新或者点击前进后退按钮的时候,能够渲染正确的组件
  • 监听popstate事件
    popstate事件只会在浏览器前进后退时触发,即调用history(go、back、forward)方法。通过监听这个事件,实现浏览器按钮点击前进、退后时,页面渲染结果与页面路劲的同步

从严格意义上来说vue项目是只有一个index.html页面的,所有的页面的切换效果,只是vue-router通过切换组件模拟出来的。

源码代码实现

监听popstate

    // set up the listeners and prepare teardown callbacks
    window.addEventListener('popstate', popStateHandler);
    // TODO: could we use 'pagehide' or 'visibilitychange' instead?
    // https://developer.chrome.com/blog/page-lifecycle-api/
    window.addEventListener('beforeunload', beforeUnloadListener, {
        passive: true,
    });

封装history对应方法

  function push(to) {
    return pushWithRedirect(to);
  }
  function replace(to) {
    return push(assign(locationAsObject(to), { replace: true }));
  }

二、hash模式实现原理

hash模式和history模式处理流程是一致的,只不过监听的事件和对url的处理逻辑不一样。
hash模式在3.0版本中,通过监听hashchange事件来实现hash改变后页面渲染与hash同步。

    const eventType = supportsPushState ? 'popstate' : 'hashchange'
    window.addEventListener(
      eventType,
      handleRoutingEvent
    )

在4.0版本中,就不再监听hashchange事件了。通过对history.pushStatereplaceState中url参数加#/,就能实现既改变了window.history对象也改变window.hash对象。把页面的路由信息存储起来

 const hashIndex = base.indexOf("#");
    const url =
      hashIndex > -1
        ? (location.host && document.querySelector("base")
            ? base
            : base.slice(hashIndex)) + to
        : createBaseLocation() + base + to;
    try {
      // BROWSER QUIRK
      // NOTE: Safari throws a SecurityError when calling this function 100 times in 30 seconds
      history[replace ? "replaceState" : "pushState"](state, "", url);
      historyState.value = state;
    } catch (err) {
      if (process.env.NODE_ENV !== "production") {
        warn("Error with push/replace State", err);
      } else {
        console.error(err);
      }
      // Force the navigation, this also resets the call count
      location[replace ? "replace" : "assign"](url);
    }

所以当浏览器前进\后退的时候,因为监听了popstate事件,所以同样能在事件处理函数中处理url改变带来的页面改变

  // set up the listeners and prepare teardown callbacks
  window.addEventListener("popstate", popStateHandler);
  // TODO: could we use 'pagehide' or 'visibilitychange' instead?
  // https://developer.chrome.com/blog/page-lifecycle-api/
  window.addEventListener("beforeunload", beforeUnloadListener, {
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

极简风格

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

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

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

打赏作者

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

抵扣说明:

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

余额充值