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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 前端路由解析(二) —— 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的源码进行解析。

相关文章
|
15天前
|
JavaScript 前端开发 开发者
Vue.js 框架大揭秘:响应式系统、组件化与路由管理,震撼你的前端世界!
【8月更文挑战第27天】Vue.js是一款备受欢迎的前端JavaScript框架,以简洁、灵活和高效著称。本文将从三个方面深入探讨Vue.js:响应式系统、组件化及路由管理。响应式系统为Vue.js的核心特性,能自动追踪数据变动并更新视图。例如,通过简单示例代码展示其响应式特性:`{{ message }}`,当`message`值改变,页面随之自动更新。此外,Vue.js支持组件化设计,允许将复杂界面拆分为独立且可复用的组件,提高代码可维护性和扩展性。如创建一个包含标题与内容的简单组件,并在其他页面中重复利用。
35 3
|
19天前
|
前端开发 UED 开发者
颠覆你的前端知识:防抖与节流的区别及实战解析!
【8月更文挑战第23天】在Web前端开发中,处理用户界面交互产生的事件可能会影响性能。为此,我们有两种优化方法:防抖(debounce)和节流(throttle)。防抖确保函数仅在事件停止触发一段时间后执行一次,适用于如搜索自动补全场景。而节流则确保函数按固定时间间隔执行,不管用户操作频率如何。本篇技术博客将深入解析两者差异并提供示例代码,帮助开发者更好地理解和应用这些技巧以提升应用性能和用户体验。
46 0
|
27天前
|
JSON 前端开发 Java
【前端学java】SpringBootWeb极速入门-请求参数解析(02)
【8月更文挑战第12天】SpringBootWeb极速入门-请求参数解析(02)
14 1
【前端学java】SpringBootWeb极速入门-请求参数解析(02)
|
19天前
|
存储 前端开发 JavaScript
深入Web前端:栈与堆的优缺点全解析,让你大开眼界!
【8月更文挑战第23天】本文以问答形式解析了Web前端开发中至关重要的内存管理概念——栈与堆。栈采用后进先出(LIFO)原则存储执行上下文,适用于函数调用管理;而堆则灵活存储如对象和数组等复杂数据类型。栈操作迅速但访问受限,堆则提供动态空间分配但可能牺牲内存效率。理解两者特性有助于提升JavaScript编程技巧。
27 1
|
22天前
|
JavaScript 算法 前端开发
"揭秘Vue.js的高效渲染秘诀:深度解析Diff算法如何让前端开发快人一步"
【8月更文挑战第20天】Vue.js是一款备受欢迎的前端框架,以其声明式的响应式数据绑定和组件化开发著称。在Vue中,Diff算法是核心之一,它高效计算虚拟DOM更新时所需的最小实际DOM变更,确保界面快速准确更新。算法通过比较新旧虚拟DOM树的同层级节点,递归检查子节点,并利用`key`属性优化列表更新。虽然存在局限性,如难以处理跨层级节点移动,但Diff算法仍是Vue高效更新机制的关键,帮助开发者构建高性能Web应用。
36 1
|
11天前
|
前端开发 UED 开发者
React组件优化全攻略:深度解析让你的前端应用飞速运行的秘诀——从PureComponent到React.memo的彻底性能比较
【8月更文挑战第31天】在构建现代Web应用时,性能是提升用户体验的关键因素。React作为主流前端库,其组件优化尤为重要。本文深入探讨了React组件优化策略,包括使用`PureComponent`、`React.memo`及避免不必要的渲染等方法,帮助开发者显著提升应用性能。通过实践案例对比优化前后效果,不仅提高了页面渲染速度,还增强了用户体验。优化React组件是每个开发者必须关注的重点。
22 0
|
19天前
|
自然语言处理 前端开发 JavaScript
前端进阶必读:JS闭包深度解析,掌握这一特性,你的代码将焕然一新!
【8月更文挑战第23天】闭包是JavaScript的一项高级功能,让函数能够访问和操作外部函数作用域中的变量。本文深入解析闭包概念、组成及应用场景。闭包由函数及其词法环境构成,通过在一个函数内定义另一个函数来创建。它有助于封装私有变量、维持状态和动态生成函数。然而,不当使用闭包可能导致内存泄漏或性能问题。掌握闭包对于实现模块化代码和成为优秀前端开发者至关重要。
29 0
|
28天前
|
JavaScript 前端开发 API
如何在 Angular 路由中使用路由解析器
如何在 Angular 路由中使用路由解析器
27 0
|
30天前
|
存储 前端开发 JavaScript
前端语言串讲 | 青训营笔记
前端语言串讲 | 青训营笔记
20 0
|
3月前
|
JSON 前端开发 JavaScript
前端Ajax、Axios和Fetch的用法和区别笔记
前端Ajax、Axios和Fetch的用法和区别笔记
62 2

热门文章

最新文章

推荐镜像

更多