对于前端路由应该都很熟悉了, 开发过 spa 应用的应该都用过, 只是很少人去查一下前端路由实现的原理.
前端路由的实现核心问题有两个, 一个是改变 url 不刷新, 另一个是监听 url 变化. 主要靠的就是 hash 和 history 两个方式.
先看看 hash,hash 属性是 url 的锚部分, 从 #开始的部分, 以前很多时候用来页面的锚点导航. hash 改变, 页面不会刷新. JS 也提供了 hashchange 事件用来监听 urlhash 的变化.
先看个效果:
在这里插入图片描述
代码:
- <a href="#home">
- home
- </a>
- <a href="#about">
- about
- </a>
- <div id="app">
- </div>
- Windows.addEventListener('hashchange', onHashChange); onHashChange();
- function onHashChange() { let router = document.getElementById('app');
- router.innerText = location.hash; }
很简单, 监听 hash 变化, 然后做相应的操作. 有一点要注意, 通过浏览器前进后退, a 标签, location 这几种情况改变 url 的 hash 都会触发 hashchange 事件. 还有, 因为刷新 hash 是不变的, 必须立马执行一次方法, 一般监听 DOMContentLoaded 的时候去执行, 我这边是直接执行了.
history 实现就比较复杂一些, history 提供了 pushState 和 replaceState 两个 API, 通过这两个方法改变 url 不会刷新页面. 但是监听 url 变化的事件 popstate, 只能是浏览器前进后退. 所以我们要通过其他方法实现监听.
效果:
在这里插入图片描述
代码:
- <a href="/home">
- home
- </a>
- <a href="/about">
- about
- </a>
- <div id="app">
- </div>
- Windows.addEventListener('popstate', popState); var router = document.getElementById('app');
- popState(); var aList = document.querySelectorAll('a[href]'); for(let i
- = 0;i
- < aList.length;i++){ aList[i].addEventListener( 'click', function (ev)
- { ev.preventDefault(); history.pushState(null, '', aList[i].getAttribute(
- 'href')) popState(); }) } function popState() { router.innerText=l ocation.pathname;
- }
pushState 换成 replaceState 效果是一样的. 这边通过监听 a 标签的点击事件, 然后阻止默认事件实现 a 标签的路由.
其实前端路由实现的原理很简单, 只是这最简单的实现在开发中并没什么用, 我们还需要加很多方法, 比如动态路由, 路由传参, 子路由等等.
最后附上一段代码:
- var arr = []
- for (i = 0; i < 10; i++) {
- arr.push(i)
- }
- console.time('for');
- for (i = 0; i < arr.length; i++) {
- }
- console.timeEnd('for');
- console.time('map');
- arr.map(function () {
- })
- console.timeEnd('map');
本人比较喜欢用 for, 是因为之前看见一句: 基于循环的迭代比基于函数的迭代快 8 倍, 现在来说, 0. 几毫秒的性能其实可以不用考虑, 在数量很少的时候差别并不明显, 只是个人习惯. 确实, 那些基于函数的循环使用更方便更快捷.
在这里插入图片描述
来源: http://www.jianshu.com/p/371212db3717