什么是路由?

个人理解路由就是浏览器 URL 和页面内容的一种映射关系。

比如你看到我这篇博客,博客的链接是一个 URL,而 URL 对应的就是我这篇博客的网页内容,这二者之间的映射关系就是路由。

其中路由又分为前端路由和后端路由,由于目前是大部门开发模式都是前后端分离开发模式,其大部分应用都是 SPA(simple Page Application,单页面应用),个人的工作也是由后端提供API,我前端来进行整个页面的渲染和路由控制。

前端路由目前实现的原理主要是:URL 的 hashHTML5 的 History

hash 模式

浏览器提供了一些 api 可以让我们获取到URL中带“#”的标识。比如 URL.hash、location.hash。

同时我们可以通过 hashchange 事件来监听hash值的改变,这样就能通过事件监听 url 中 hash 的改变从而改变特定页面元素的显示内容,从而实现前端路由。简单实现代码如下:

<div id="app">
<a href="#/home">home</a>
<a href="#/about">about</a> <div class="router-view"></div>
</div>
// 1.获取路由显示元素
const routerViewEl = document.querySelector('.router-view'); // 2.监听 hashchange 事件
window.addEventListener('hashchange', () => {
// 3.判断 hash 的改变值,修改路由显示元素的 innerHTMl
switch (location.hash) {
case '#/home':
routerViewEl.innerHTML = 'Home';
break;
case '#/about':
routerViewEl.innerHTML = 'about';
break;
default:
routerViewEl.innerHTML = 'default';
}
});

History 模式

history 接口是 HTML5 新增的, 它有六种模式改变 URL 而不刷新页面。

  • pushState:使用新的路径;
  • replaceState:替换原来的路径;
  • popState:路径的回退;
  • go:向前或向后改变路径;
  • forward:向前改变路径;
  • back:向后改变路径;

其中比较重要的两个 api 是 pushState 和 replaceState 是比较重要的,是实现 history 模式的重要 api。

首先我们用 pushState 来简单实现下,代码如下:

<div id="app">
<a href="/home">home</a>
<a href="/about">about</a> <div class="router-view"></div>
</div>
// 1.获取路由显示元素
const routerViewEl = document.querySelector('.router-view'); // 2.获取所有路由跳转元素
const aEls = document.getElementsByTagName('a');
// 3.遍历所有 a 元素,注册事件监听点击
for (let aEl of aEls) {
aEl.addEventListener('click', (e) => {
// 4.阻止默认跳转
e.preventDefault();
// 5.获取 href 属性
const href = aEl.getAttribute('href');
// 6.执行 history.pushState
history.pushState({}, '', href);
// 7.判断 pathname 路径的改变
switch (location.pathname) {
case '/home':
routerViewEl.innerHTML = 'Home';
break;
case '/about':
routerViewEl.innerHTML = 'about';
break;
default:
routerViewEl.innerHTML = 'default';
}
});
}

相同之处是两个 API 都会操作浏览器的历史记录,而不会引起页面的刷新。

不同之处在于,pushState 会增加一条新的历史记录,而 replaceState 则会替换当前的历史记录。其内部原理是 pushState 每次前进一次页面都是入栈操作,每次返回又是出栈,因此使用 pushState ,浏览器可以执行本身的前进后退操作,其内部就是一个入栈出栈;而 replaceState 就不可,它是把每次栈底的数据替换,而不是入栈。

pushState 栈:[]->点击 home 入栈->[home]->点击 about 入栈->[home,about]->浏览器回退,about 出栈->[home]

replaceState 栈:[]->点击 home 入栈->[home]->点击 about 替换栈底->[about]

如果把代码改成 replaceState 实现。那么就不能操作浏览器上面的前进后退操作。

// 1.获取路由显示元素
const routerViewEl = document.querySelector('.router-view'); // 2.获取所有路由跳转元素
const aEls = document.getElementsByTagName('a');
// 3.遍历所有 a 元素,注册事件监听点击
for (let aEl of aEls) {
aEl.addEventListener('click', (e) => {
// 4.阻止默认跳转
e.preventDefault();
// 5.获取 href 属性
const href = aEl.getAttribute('href');
// 6.执行 history.replaceState
// history.pushState({}, '', href);
history.replaceState({}, '', href);
// 7.判断 pathname 路径的改变
switch (location.pathname) {
case '/home':
routerViewEl.innerHTML = 'Home';
break;
case '/about':
routerViewEl.innerHTML = 'about';
break;
default:
routerViewEl.innerHTML = 'default';
}
});
}

参考文章

前端路由的两种实现原理

前端路由原理之 hash 模式和 history 模式的更多相关文章

  1. 【前端路由】Vue-router 中hash模式和history模式的区别

    咱们今天说说VUE路由的hash模式与history模式的区别,这个也是面试常问的问题,不要小看这道题其实问到这里的时候那个面试官应该是个大牛,开发经验丰富,这个题其实就是考验你的开发经验是否属实. ...

  2. 前端路由的两种模式: hash 模式和 history 模式

    随着 ajax 的使用越来越广泛,前端的页面逻辑开始变得越来越复杂,特别是spa的兴起,前端路由系统随之开始流行. 从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下): 记 ...

  3. 前端路由的两种模式:hash(#)模式和history模式(转)

    随着 ajax 的使用越来越广泛,前端的页面逻辑开始变得越来越复杂,特别是spa的兴起,前端路由系统随之开始流行. 从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下): 记 ...

  4. Vue路由的hash模式与history模式的区别?

    1.首先router有两种模式:hash模式(默认).history模式(需配置mode: 'history') hash和history的区别?   hash                    ...

  5. 前端路由原理及vue-router介绍

    前端路由原理本质就是监听 URL 的变化,然后匹配路由规则,显示相应的页面,并且无须刷新.目前单页面使用的路由就只有两种实现方式 hash history www.test.com/##/ 就是 Ha ...

  6. vue-router的hash模式与history模式的对比

    Vue-router 中hash模式和history模式的关系在vue的路由配置中有mode选项 最直观的区别就是在url中 hash 带了一个很丑的 # 而history是没有#的mode:&quo ...

  7. Vue-router 中hash模式和history模式的区别

    实际上存在三种模式: Hash: 使用URL的hash值来作为路由.支持所有浏览器. History: 以来HTML5 History API 和服务器配置.参考官网中HTML5 History模式 ...

  8. hash模式与history模式

    随着 ajax 的使用越来越广泛,前端的页面逻辑开始变得越来越复杂,特别是spa的兴起,前端路由系统随之开始流行. 从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下): 记 ...

  9. Vue中hash模式和history模式的区别

    vue-router 中hash模式和history模式. 在vue的路由配置中有mode选项,最直观的区别就是在hash模式下的地址栏里的URL夹杂着‘#’号 ,而history模式下没有.vue默 ...

随机推荐

  1. 一些Shell脚本记录

    查看换行符 使用vim打开文件,输入:set ff?.根据返回结果可以文件类型 字符串 opcenter.sjb.bz [root@opcenter backup]# echo ${HOSTNAME% ...

  2. Docker限制

    前言 Docker系列文章: 此篇是Docker系列的第十篇,大家一定要按照我做的Demo都手敲一遍,印象会更加深刻的,马上就开始Kubernetes,加油!一起前行! 为什么要学习Docker Do ...

  3. MySQL执行计划【explain】详解

    本文已经收录到github仓库,仓库用于分享Java相关知识总结,包括Java基础.MySQL.Springboot.mybatis.Redis.rabbitMQ等等,欢迎大家提pr和star! gi ...

  4. SQL语句(五)子查询

    目录 一.子查询含义 二.子查询分类 按子查询的位置分 按结果集的行列数不同分 三.WHERE后面的子查询 1. 标量子查询 2. 列子查询(多行子查询) 3. 行子查询(结果为一行多列或多行多列) ...

  5. CTF中的序列化与反序列化

    记一些CTF出现的序列化与反序列化的知识点和题目. 序列化和反序列化的概念 序列化就是将对象转换成字符串.字符串包括 属性名 属性值 属性类型和该对象对应的类名. 反序列化则相反将字符串重新恢复成对象 ...

  6. 用传纸条讲 HTTPS

    我和小宇早恋了,上课的时候老说话. 老师把我们的座位分得很远,我在第一排,她在最后一排,我们中间隔了很多人. 但我们还是想通过传纸条的方式交流. 我们中间的那些同学,虽然坏心思比较多,但好在可以保证将 ...

  7. Linux命令(九)之安装mysql

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

  8. Http协议中的CharacterEncoding、Content-Encoding和Transfer-Encoding

    https://www.cnblogs.com/jinzhiming/p/5765672.html https://www.jianshu.com/p/e918a65b617f https://www ...

  9. Python--数据存储

    新建测试文档测试.txt内容如下: 张三:今天天气真好. 李四:是的,真的太好了. 张三:阳光明媚. 李四:鸟语花香. 王五:装逼现场:请带好安全帽 张三:难得好天气,今天就不偷懒了. 李四:能把乞讨 ...

  10. 【死磕 Java 基础】 — 自己动手实现一个 LRU

    大家好,我是大明哥,一个专注于[死磕 Java]系列创作的男人 个人网站:https://www.cmsblogs.com/.专注于 Java 优质系列文章分享,提供一站式 Java 学习资料 LRU ...