路由放在前端意味着什么?

路由放在前端意味着什么?

一. 前端路由

现代前端开发中最流行的页面模型,莫过于SPA单页应用架构。单页面应用指的是应用只有一个主页面,通过动态替换DOM内容并同步修改url地址,来模拟多页应用的效果,切换页面的功能直接由前台脚本来完成,而不是由后端渲染完毕后前端只负责显示。前端三驾马车Angular,Vue,React均基于此模型来运行的。SPA能够以模拟多页面应用的效果,归功于其前端路由机制

前端路由,顾名思义就是一个前端不同页面的状态管理器,可以不向后台发送请求而直接通过前端技术实现多个页面的效果。angularjs中的ui-router,vue中的vue-router,以及react的react-router均是对这种功能的具体实现。

路由转移到前端,正是前后端分离和单页应用架构的基石。
在这里插入图片描述

二.前端路由实现基础

默认情况下,当地址栏的 URL 发生变化时,浏览器会向服务端发起新的请求。所以实现前端路由的重要基础就是在修改 URL 时,不引起浏览器向后端请求数据。根据浏览器提供的 API,有下面两种实现方案。

  • 哈希路由通过在 URL 中添加一个哈希值来实现页面的切换

  • HTML5 历史 API 则通过在浏览器历史记录中添加新的条目来实现页面的切换。

    在这里插入图片描述

1.基于 hash 实现

hash 值是指 URL“#”号后面的内容,通过 location.hash 属性可以读写 hash 值,这个值可以让浏览器将页面滚动到 ID 与 hash 值相等的 DOM 元素位置,不会传给服务端。

要监听它的变化也比较简单,通过监听 window 对象的 hashchange 事件就可以感知到它的变化。
这种实现方式占用了 hash 值,导致默认的页面滚动行为失效,对于有滚动定位需求的情况需要自行手动获取元素的位置并调用 BOM 相关 API 进行滚动。

HTML页面中通过锚点定位原理可进行无刷新跳转,触发后url地址中会多出# + 'XXX'的部分,同时在全局的window对象上触发hashChange事件,这样在页面锚点哈希改变为某个预设值的时候,通过代码触发对应的页面DOM改变,就可以实现基本的路由了,基于锚点哈希的路由比较直观,也是一般前端路由插件中最常用的方式。

2.基于 history 实现

浏览器访问一个页面时,当前地址的状态信息会被压入历史栈,当调用history.pushState()方法向历史栈中压入一个新的state后,历史栈顶部的指针是指向新的state的。可以将其作用简单理解为 假装已经修改了url地址并进行了跳转 ,除非用户点击了浏览器的前进,回退,或是显式调用HTML4中的操作历史栈的方法,否则不会触发全局的popstate事件。

HTML5History API为浏览器的全局history对象增加的扩展方法。一般用来解决ajax请求无法通过回退按钮回到请求前状态的问题

在HTML4中,已经支持window.history对象来控制页面历史记录跳转,常用的方法包括:

  • history.forward(); //在历史记录中前进一步
  • history.back(); //在历史记录中后退一步
  • history.go(n): //在历史记录中跳转n步骤,n=0为刷新本页,n=-1为后退一页。

在HTML5中,window.history对象得到了扩展,新增的API包括:

  • history.pushState(data[,title][,url]);//向历史记录中追加一条记录
  • history.replaceState(data[,title][,url]);//替换当前页在历史记录中的信息。
  • history.state;//是一个属性,可以得到当前页的state信息。
  • window.onpopstate;//是一个事件,在点击浏览器后退按钮或js调用forward()、back()、go()时触发。监听函数中可传入一个event对象,event.state即为通过pushState()或replaceState()方法传入的data参数。
3.hash 和 history API对比

在这里插入图片描述
在这里插入图片描述

三.亲手造一个简单的前端路由插件
3.1基于Hash的前端路由插件myHashRouter.js

我们希望实现的功能是:

  • 1.引入MyHashRouter.js

  • 2.通过when()方法来定义若干不同的路由状态

  • 3.通过init()方法启动路由功能

  • 4.通过点击导航实现前端路由切换

    在这里插入图片描述

3.2基于History API的前端路由插件myHistoryRouter.js

由于History API不支持低于IE10以下版本的浏览器(其他大多数现代浏览器基本都支持),所以我们在init()方法启动时先进行可用性判断,基本代码框架与基于Hash的路由插件一致

四.路由解析

阻止浏览器在 URL 变化时向后端发送请求之后,就需要对路由进行解析了。 vue-router和 react-router都同时依赖了一个第三方库 Path-to-RegExp进行路由解析,源码很短小,收获很多,有兴趣可以看下,下面通过分析 path-to-regexp 1.8 版本的源码来理解路由是如何被解析的。
路由解析又分为两个操作:路由匹配和路由生成

  • pathToRegexp() 会先将配置的请求路径字符串拆分成令牌数组,然后再转化成正则表达式对象,路由库可以通过正则表达式来进行路由匹配,从而将对应的组件渲染到页面;
  • complie() 函数会将配置的请求路径字符串转化成一个匿名函数,这个函数可以传入参数并生成一个请求路径字符串。
五.前端路由的挑战和解决方案

在使用前端路由时,可能会遇到一些挑战,包括 SEO 问题、浏览器兼容性等。下面将对这些挑战进行讨论:

  1. SEO 问题:由于前端路由是通过修改 URL 来实现页面的无刷新切换,而搜索引擎爬虫通常无法正确解析前端路由生成的 URL。这可能导致搜索引擎无法正确索引页面内容,从而影响网站的 SEO 排名。为了解决这个问题,可以使用服务器端渲染(SSR)或预渲染技术来生成对搜索引擎友好的静态页面。
  2. 浏览器兼容性:前端路由依赖于现代浏览器的 History API 来实现 URL 的修改和页面的切换。然而,旧版本的浏览器可能不支持 History API,这可能导致前端路由在这些浏览器上无法正常工作。为了确保浏览器兼容性,可以使用兼容性库(如 HashRouter)或提供降级处理。
  3. 状态管理:在单页应用中,页面的状态需要在页面切换时进行保存和恢复。前端路由本身并不提供状态管理功能,因此需要结合其他状态管理库(如 Vuex、Redux)来实现状态的持久化和共享
  4. 代码复杂度:前端路由的实现可能会增加代码的复杂度,尤其是在处理嵌套路由和动态路由时。为了降低代码复杂度,可以使用成熟的前端框架(如 Vue.js、React),它们通常提供了简洁高效的路由解决方案。
  5. 性能问题:前端路由可能会对页面的加载性能产生一定的影响。为了优化性能,可以使用懒加载技术来按需加载页面组件,减少初始页面加载的资源。

总之,在使用前端路由时,需要考虑到 SEO 问题、浏览器兼容性、状态管理、代码复杂度和性能等挑战。通过合理的解决方案和最佳实践,可以有效地应对这些挑战,提高 Web 应用的质量和用户体验。

六.造轮子的思考

【造轮子】是学习和理解一些较复杂的代码结构时的常用方法,它很慢,但是效果却胜过你读十几篇相关的文章。为已知的API方法自行编写实现,遇到自己无法复现的部分再有针对性地去查资料,最后当你再去学习官方代码的时候,就会明白这样做的价值。
【造轮子】不是为了把它装在你的车上,而是当你在荒郊野外开车而轮子出了问题时多一种选择。
【造轮子】是一个很好的学习方式,虽然自己造的车轮很简陋,但是对于理解工具的底层原理却很有帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值