前端路由的两种模式

Hash History

平时单页面网站经常使用的模式,# 有两种情况,一个是我们所谓的锚点,比如典型的回到顶部按钮原理、Github 上各个标题之间的跳转等,路由里的 # 不叫锚点,我们称之为 hash,大型框架的路由系统大多都是哈希实现的。
Angular1,vue-router,react-router都支持该模式

实现原理

改变#不触发网页重载
比如

http://www.example.com/index.html#location1 
// 改成
http://www.example.com/index.html#location

浏览器不会重新向服务器请求index.html。

改变#会改变浏览器的访问历史
每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。

onhashchange事件去监测hash的变更
三种实现方式

window.onhashchange = func;
<body onhashchange="func();">
window.addEventListener("hashchange", func, false);

具体实现代码

<button onclick="link('/a')">to /a</button>
<button onclick="link('/b')">to /b</button>
<script>
function link(url) {
  console.log('link to: ' + url);
  window.location = '#' + url;
}

window.addEventListener("hashchange", function() {
  var hash = window.location.hash;
  console.log('current hash: ' + hash);
}, false);
</script>

缺点

SEO
页面都变成了全JS生成,搜索引擎及第三方统计无法进行抓起
解决方案:
一:Google抓取AJAX方案
二:再做一个服务端生成内容的镜像网站
三:HTML5 history 中的PushState(另外一种路由模式)


HTML5 history

这种路由模式下,没有难看的#号,url与后台路由看起来没有差别。
vue-router,react-router都支持该模式

实现原理

HTML5 新增的历史记录 API 可以实现无刷新更改地址栏链接,配合 AJAX 可以做到无刷新跳转。

window.history.pushState(null, null, "/profile/");

参见 MDN pushState API

popstate 事件
当用户点击浏览器的「前进」、「后退」按钮时,就会触发popstate事件。你可以监听这一事件,从而作出反应。

window.addEventListener("popstate", function(e) {
    var state = e.state;
    // do something...
});

这里e.state就是当初pushState时传入的第一个参数,state 对象可以是任何可以序列化的东西。由于 火狐 会将这些对象存储在用户的磁盘上,所以用户在重启浏览器之后这些state对象会恢复。参见 MDN pushState API

replaceState 方法
有时,你希望不添加一个新记录,而是替换当前的记录(比如对网站的 landing page),则可以使用replaceState方法。这个方法和pushState的参数完全一样。

具体实现代码

<button onclick="link('/a')">to /a</button>
<button onclick="link('/b')">to /b</button>
<script>
function link(url) {
  console.log('link to: ' + url);
  window.history.pushState(null, null, url);
}

// 仅仅调用pushState方法或replaceState方法 ,并不会触发该事件,只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发
window.addEventListener('popstate', function(e) {
  alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
}, false);

</script>

缺点

当使用HTML5 history,刷新页面时会出现404。是因为当前url服务端无法找到,所以,要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。同时需要在前端这边处理404


参考:
[1] 阮一峰 URL的井号 http://www.ruanyifeng.com/blog/2011/03/url_hash.html
[2] orangexc 前端路由的两种实现原理 https://segmentfault.com/a/1190000007238999
[3] Renfei Song's Blog HTML5 简介(三):利用 History API 无刷新更改地址栏 https://www.renfei.org/blog/html5-introduction-3-history-api.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 什么是前端路由路由,引导、指路之意。 譬如我们熟知的路由器,蹦跶在网络层的数据包转发设备,在网络中也是扮演着指路明...
    蓝浅蓝深阅读 779评论 0 5
  • 本文总结自:Web开发中 前端路由 实现的几种方式和适用场景HTML 5 History API的”前生今世”从零...
    始悔不悟阅读 1,685评论 0 2
  • 原文见martin的博客 最近一直在研究前后端分离,ajax可以很好的解决前后端分离的问题,但是又存在着浏览器无法...
    small_a阅读 9,695评论 4 34
  • 1. 什么是路由 在Web开发过程中,经常会遇到『路由』的概念。那么,到底什么是路由?简单来说,路由就是URL到函...
    JS大神阅读 887评论 0 1
  • “聪明的人都在思考奔跑,平庸的人还在呻吟”,当你读到这句话的时候不知你作何感想,也许你会骂我矫情,也许你会停下思考...
    lowett阅读 306评论 2 0