写在前面
现在的前端应用很多都是单页应用。路由对于单页应用来说,是一个重要的组成部分。本系列文章将讲解前端路由的实现原理。这是系列文章的第一篇:hash路由。
hash
首先来说一说什么是hash。我们经常能看到这种url:
1、https://www.baidu.com/#1232、https://www.baidu.com/#234
url后面的#/123
,就是hash值,可以通过下面的代码来获取:
window.location.hash// #123// #234
hash最初是用来进行页面快速定位的,当页面很长的时候,是很有用的,比如下面的例子:
<header> <a href='#p1'>前往段落1</a> <a href='#p2'>前往段落2</a> <a href='#p3'>前往段落3</a></header><main> <p id='p1'>11111111111111111111111111</p> <p id='p2'>22222222222222222222222222</p> <p id='p3'>33333333333333333333333333</p></main>
假设我们的三个</p>
上下间距很大,点击最上面的</a>
标签,可以迅速定位到对应的段落。像下面这样:
我们也可以用过代码来控制hash
值,同样可以达到定位的效果,比如:
window.location.hash = '#p2'
hash路由
当页面的hash值变化时,是可以监听到的:
window.addEventListener('hashchange', e => { console.log(e); // HashChangeEvent const oldUrl = e.oldURL; // 旧的页面地址 const newUrl = e.newURL; // 新的页面地址 const type = e.type // hashchange - 事件类型 const cancelable = e.cancelable; // false - 表示该事件无法取消。即无法通过e.preventDefault()阻止hash跳转});
hash路由就是利用了hash值变化可监听这一点来实现的。我们来实现一个最最简单的:
<body> <header> <a href='#p1'>前往段落1</a> <a href='#p2'>前往段落2</a> <a href='#p3'>前往段落3</a> </header> <main> <div id="content"> 这是首页 </div> </main> <script> const routerMap = { 'p1': () => { document.getElementById('content').innerHTML = '这是段落1的内容' }, 'p2': () => { document.getElementById('content').innerHTML = '这是段落2的内容' }, 'p3': () => { document.getElementById('content').innerHTML = '这是段落3的内容' }, } const handleRouter = e => { const newURL = e && e.newURL || window.location.href; const newHash = newURL.split('#').pop(); typeof routerMap[newHash] === 'function' && routerMap[newHash](); }; window.addEventListener('hashchange', handleRouter); window.addEventListener('load', handleRouter);</script></body>
最终的效果如下图所示:
hash路由的兼容性很不错,可以兼容到IE8。并且,hash路由完全由前端就可以实现。
写在后面
本文解析了前端的hash,以及hash路由的实现原理,符合预期。其实很多看起来强大的功能,底层的原理其实很简单。后续会解析另一种常用的路由方式:history路由。
另外,一些我们平时不常用的api等,或许可以做很多事情。比如我之前这篇文章里讲的: