前端路由原理之 hash 模式和 history 模式
什么是路由?
个人理解路由就是浏览器 URL 和页面内容的一种映射关系。
比如你看到我这篇博客,博客的链接是一个 URL,而 URL 对应的就是我这篇博客的网页内容,这二者之间的映射关系就是路由。
其中路由又分为前端路由和后端路由,由于目前是大部门开发模式都是前后端分离开发模式,其大部分应用都是 SPA(simple Page Application,单页面应用),个人的工作也是由后端提供API,我前端来进行整个页面的渲染和路由控制。
前端路由目前实现的原理主要是:URL 的 hash、HTML5 的 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 模式的更多相关文章
- 【前端路由】Vue-router 中hash模式和history模式的区别
咱们今天说说VUE路由的hash模式与history模式的区别,这个也是面试常问的问题,不要小看这道题其实问到这里的时候那个面试官应该是个大牛,开发经验丰富,这个题其实就是考验你的开发经验是否属实. ...
- 前端路由的两种模式: hash 模式和 history 模式
随着 ajax 的使用越来越广泛,前端的页面逻辑开始变得越来越复杂,特别是spa的兴起,前端路由系统随之开始流行. 从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下): 记 ...
- 前端路由的两种模式:hash(#)模式和history模式(转)
随着 ajax 的使用越来越广泛,前端的页面逻辑开始变得越来越复杂,特别是spa的兴起,前端路由系统随之开始流行. 从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下): 记 ...
- Vue路由的hash模式与history模式的区别?
1.首先router有两种模式:hash模式(默认).history模式(需配置mode: 'history') hash和history的区别? hash ...
- 前端路由原理及vue-router介绍
前端路由原理本质就是监听 URL 的变化,然后匹配路由规则,显示相应的页面,并且无须刷新.目前单页面使用的路由就只有两种实现方式 hash history www.test.com/##/ 就是 Ha ...
- vue-router的hash模式与history模式的对比
Vue-router 中hash模式和history模式的关系在vue的路由配置中有mode选项 最直观的区别就是在url中 hash 带了一个很丑的 # 而history是没有#的mode:&quo ...
- Vue-router 中hash模式和history模式的区别
实际上存在三种模式: Hash: 使用URL的hash值来作为路由.支持所有浏览器. History: 以来HTML5 History API 和服务器配置.参考官网中HTML5 History模式 ...
- hash模式与history模式
随着 ajax 的使用越来越广泛,前端的页面逻辑开始变得越来越复杂,特别是spa的兴起,前端路由系统随之开始流行. 从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下): 记 ...
- Vue中hash模式和history模式的区别
vue-router 中hash模式和history模式. 在vue的路由配置中有mode选项,最直观的区别就是在hash模式下的地址栏里的URL夹杂着‘#’号 ,而history模式下没有.vue默 ...
随机推荐
- Jmeter分布式压测实战及踩坑处理(含参数化)
项目中使用Jmeter进行大并发压测时,单机受限内存.CPU.网络IO,会出现服务器压力还没有上 去,但压测服务器由于模拟的压力太大死机的情况.JMeter的集群模式可以让我们将多台机器联合起来 一起 ...
- 8.8考试总结(NOIP模拟33)[Hunter·Defence·Connect]
无法逃避的是自我,而无法挽回的是过去. 前言 还算可以,不过 T1 少 \(\bmod\) 了一下挂了 25pts,T2 没看清题面挂了 27pts. 下回注意吧.. T1 Hunter 解题思路 感 ...
- BUU八月份水题记录
目录 [BJDCTF 2nd]fake google(SSTI) [BJDCTF2020]Easy MD5(md5注入) [ZJCTF 2019]NiZhuanSiWei(反序列化) [BJDCTF ...
- 腾讯开源:Kotlin 高性能特效动画组件!
先看一下效果展示: 1. VAP VAP(Video Animation Player)是企鹅电竞开发,用于播放酷炫动画的实现方案. 相比Webp, Apng动图方案,具有高压缩率(素材更小).硬件解 ...
- 线程状态Thread.State
线程状态Thread.State 线程状态.线程可以处于下列状态之一: NEW 至今尚未启动的线程处于这种状态. RUNNABLE 正在 Java 虚拟机中执行的线程处于这种状态. BLOCKED 受 ...
- A*算法寻路(C++代码实现)
A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法.算法中的距离估算值与实际值越接近,最终搜索速度越快.--来自百度百科. 我在网上看了不少关于A ...
- 1009 Product of Polynomials (25分) 晚上脑子就是容易僵住
#include<iostream> using namespace std; struct { int a; double b; }poly[1001]; double a[2001]; ...
- Docker与k8s的恩怨情仇(八)——蓦然回首总览Kubernetes
在系统介绍了如何实际部署一个K8S项目后,作为本系列文章的最后一篇,我们一起来看看Kubernetes集群内容总览,再对一些更深层次的功能进行总结. Kubernetes总览 下图是一个k8s的总览结 ...
- springboot项目出现Whitelabel Error Page的问题
springboot项目出现Whitelabel Error Page的问题 大概就是这种情况,然而昨天还是没问题的,通过对比就发现,是自己手欠了 简单来说解决办法就是将springboot的启动项目 ...
- nohup 启动命令
start.sh #!/bin/bash nohup $PWD/node_exporter > /dev/null 2>&1 &