前端路由解析(二) —— history路由

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 前端路由解析(二) —— history路由

640.jpg

写在前面


现在的前端应用很多都是单页应用。路由对于单页应用来说,是一个重要的组成部分。本系列文章将讲解前端路由的实现原理。这是系列文章的第二篇:history路由。


系列文章第一篇:前端路由解析(一) ——  hash路由


history api


HTML5引入了history.pushStatehistory.replaceState方法,他们分别可以添加和修改历史记录条目。pushStatereplaceState都接收三个参数:

  1. state: 一个JS对象。在popstate事件中使用。
  2. title: 标题。一般浏览器都忽略这个参数。
  3. url:  任意url,可以是相对路径,也可以是绝对路径。但是必须与当前url同源。

一个pushState的例子,假如我们在https://www.google.com/执行以下代码:


let stateObj = {    foo: "bar",};
history.pushState(stateObj, "page 2", "bar.html");


浏览器的地址栏将变成:https://www.google.com/bar.html

但是,浏览器并不会刷新。此时,history.state的值为:{foo: "bar"}

我们点击浏览器的后退按钮,浏览器会重新回到https://www.google.com/

replaceStatepushState的用法一样,仅有一处不同:

history.pushState是在保留当前记录记录的基础上,再添加一个新的url。而history.replaceState是将当前历史记录替换为新的url。


什么时候会触发popstate事件呢?无论什么时候用户导航到新的状态,popstate事件就会被触发。举个例子,我们在某个页面执行下面的代码:


history.pushState({ page: 1 }, '', 'page1.html');history.pushState({ page: 2 }, '', 'page2.html');


执行完成后,页面会链接为:xxxx/page2.html

此时,点击浏览器后退按钮,页面会回到 xxxx/page1.html,并且会触发一次popstate事件,且事件对象的state参数值为:{ page: 1}。再次点击浏览器历史记录前进按钮,页面回到 xxxx/page2.html,触发一次popstate事件,事件对象的state参数值为:{page : 2}


history路由


history路由就是通过history.pushStatehistory.replaceState 以及 popstate来实现的。我们实现一个最简单的,包含下面两个方面功能:


1、用户点击a标签,可以进行路由跳转。

2、用户点击浏览器的前进后退按钮,可以进行路由跳转。


<html>  <body>      <a href='/p1'>page1</a>      <a href='/p2'>page2</a>      <a href='/p3'>page3</a>      <main>          <div id="content">              这是首页          </div>      </main>  </body>  <script>  window.onload = function () {
    const routerMap = {        '/p1': () => {            document.getElementById('content').innerHTML = '这是段落1111的内容'        },        '/p2': () => {            document.getElementById('content').innerHTML = '这是段落22222的内容'        },        '/p3': () => {            document.getElementById('content').innerHTML = '这是段落33333的内容'        },    };
    const handleRoute = function(inputUrl) {        const url = '/' + inputUrl;        const routeCb = routerMap[url];        if(typeof routeCb === 'function') {            routeCb();        }    }
    window.onpopstate = function (e) {        const url = e.state && e.state.url || '';        url &&  handleRoute(url);    }
    document.addEventListener('click', e => {                if(e.target.tagName !== 'A') return;        e.preventDefault();
        const href = e.target.getAttribute('href');        if(!href) return;
        const url = href.split('/').pop();        window.history.pushState({ url }, null , url);        handleRoute(url);    });  }</script></html>


最终的效果如下:

640.gif


这里需要注意的是,history路由往往需要服务端的配合。虽说 history api 不会刷新页面,但是当用户处在某一个路由并刷新页面时,或者用户直接访问带有路由的页面时,如果服务端没有对当前url进行处理,那么很可能就直接404了。所以需要服务端把相关的url,全都匹配到对应的单页应用的html上。


history路由和hash路由对比


结合之前的hash路由原理,我们可以简单对比一下:


1、history路由比hash路由"长"得好看一下,毕竟url里面带有#看起来不太美观。

2、history路由兼容性不够完美,毕竟是使用了html5标准的api,并且,history路由往往需要服务端的配合。

3、hash路由的兼容性更好。


在实际项目中,根据自己的实际情况来选择使用哪种路由就好了。


写在后面


本文解析了history api,以及history路由的实现原理,符合预期。后续会对react-router的源码进行解析。

相关文章
|
2天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
13 1
|
2天前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
8 1
|
7天前
|
缓存 前端开发 JavaScript
前端的全栈之路Meteor篇(二):容器化开发环境下的meteor工程架构解析
本文详细介绍了使用Docker创建Meteor项目的准备工作与步骤,解析了容器化Meteor项目的目录结构,包括工程准备、环境配置、容器启动及项目架构分析。提供了最佳实践建议,适合初学者参考学习。项目代码已托管至GitCode,方便读者实践与交流。
|
6天前
|
人工智能 资源调度 数据可视化
【AI应用落地实战】智能文档处理本地部署——可视化文档解析前端TextIn ParseX实践
2024长沙·中国1024程序员节以“智能应用新生态”为主题,吸引了众多技术大咖。合合信息展示了“智能文档处理百宝箱”的三大工具:可视化文档解析前端TextIn ParseX、向量化acge-embedding模型和文档解析测评工具markdown_tester,助力智能文档处理与知识管理。
|
13天前
|
存储 JavaScript 前端开发
Vue3权限控制全攻略:路由与组件层面的用户角色与权限管理方法深度解析
Vue3权限控制全攻略:路由与组件层面的用户角色与权限管理方法深度解析
55 2
|
12天前
|
JSON 前端开发 JavaScript
前端模块打包器的深度解析
【10月更文挑战第13天】前端模块打包器的深度解析
|
12天前
|
存储 前端开发 JavaScript
前端模块化打包工具的深度解析
【10月更文挑战第13天】前端模块化打包工具的深度解析
|
19天前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
39 0
|
19天前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
29 0
|
19天前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
33 0

推荐镜像

更多