Router中Hash和history的简单实现

Router 是路由管理工具,Vue,React 中分别常用的是 vue-routerreact-router-dom

在探究其实现原理前,我们先来复习一下 Location 对象

请添加图片描述

Location 对象中包含有关当前 URL 的信息。

而当浏览器 URL 发生改变后 PopStateEvent 事件。

window.addEventListener('popstate', e => {
  console.log(e);
});

vue-routerreact-router-dom 分别 Hash 模式和 History 模式

  • Hash 路由带有 # 号,比如现在网易云音乐就是采用的 Hash 模式。(不美观)

  • History 变化页面会刷新,Hash 变化页面不会刷新

  • 设置 Hash 需要在服务端设置静态资源 index.htmlHistory 不需要设置

Hash 模式的实现

思路:我们需要监听 Hash 的变化,从而渲染不同的页面

浏览器为我们提供了 Hash 变化的 HashChangeEvent 的事件,我们可以直接监听

window.addEventListener('hashchange', e => {
  console.log('hash change', e);
});
<a href="#/index">index</a>
<a href="#/home">home</a>

在这里插入图片描述

监听到了 Hash 的变化,那么我们在来根据 Hash 来获取当前 Hash 需要展示的内容给渲染出来

window.addEventListener('hashchange', e => {
  console.log('hash change', e);
  renderDOM(location.hash);
});

function renderDOM(path) {
  let _path = path.replace(/^#\//gi, '');
  let app = document.getElementById('app');
  app.innerHTML = '';
  let ele = document.createElement('div');
  ele.innerHTML = `<h1>${_path}</h1>`;
  app.appendChild(ele);
}

在这里插入图片描述

History 模式的实现

思路:我们需要监听 History 的变化,并且阻止页面的跳转,从而渲染不同的页面

在复习 Location 的时候我们提到了 PopStateEvent 事件,当页面发生改变的时候会被触发。

let els = document.getElementsByTagName('a');

for (let el of els) {
  el.addEventListener('click', e => {
    // 阻止默认行为
    e.preventDefault();
    // 获取即将跳转的页面
    let path = el.getAttribute('href');
    renderDOM(path);
  });
}

function renderDOM(path) {
  let _path = path.replace(/\//gi, '');
  let app = document.getElementById('app');
  app.innerHTML = '';
  let ele = document.createElement('div');
  ele.innerHTML = `<h1>${_path}</h1>`;
  app.appendChild(ele);
}

请添加图片描述

此时我们页面的视图发生了改变,但是页面的路由没有变化,应为我们为了不让页面跳转,阻止了 a 标签的默认行为,所以无法跳转

History 对象为我们提供了 pushStateAPI 改变路由,我们在每次路由切换的时候调用即可实现路由的变化

history.pushState({}, '', path);

拓展

当我们刷新浏览器时,页面会 404,这个行为让我们联想到一个 History 模式下 SPA 应用程序刷新会404,原因就在于当前资源在静态文件中不存在,所以我们需要配置一个 默认静态资源 index.html

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值