1. 前端路由主要由两种方式实现
有一个路由表,以 path 为 key,value 是触发给 path 的回调函数。
location.hash + hashchange
history.pushState() + popState
1.1. location.hash, hashchange
说一下前端路由实现的简要原理,以 hash 形式(也可以使用 History API 来处理)为例,当 url 的 hash 发生变化时,触发 hashchange
注册的回调,回调中去进行不同的操作,进行不同的内容的展示。直接看代码或许更直观。
缺点:url 不好看,不利于 SEO
function Router() {
this.routes = {};
this.currentUrl = '';
}
Router.prototype.route = function(path, callback) {
this.routes[path] = callback || function() {};
};
Router.prototype.refresh = function() {
this.currentUrl = location.hash.slice(1) || '/';
this.routes[this.currentUrl]();
};
Router.prototype.init = function() {
window.addEventListener('load', this.refresh.bind(this), false);
window.addEventListener('hashchange', this.refresh.bind(this), false);
};
window.Router = new Router();
window.Router.init();
上面路由系统 Router 对象实现,主要提供三个方法
- init 监听浏览器 url hash 更新事件
- route 存储路由更新时的回调到回调数组 routes 中,回调函数将负责对页面的更新
- refresh 执行当前 url 对应的回调函数,更新页面
Router 调用方式以及呈现效果如下:点击触发 url 的 hash 改变,并对应地更新内容(这里为 body 背景色)
<ul>
<li><a href="#/">turn white</a></li>
<li><a href="#/blue">turn blue</a></li>
<li><a href="#/green">turn green</a></li>
</ul>
var content = document.querySelector('body');
// change Page anything
function changeBgColor(color) {
content.style.backgroundColor = color;
}
Router.route('/', function() {
changeBgColor('white');
});
Router.route('/blue', function() {
changeBgColor('blue');
});
Router.route('/green', function() {
changeBgColor('green');
});
1.2. History Api: history.pushState() + popstate
- history.pushState(data, title, url): 修改 url 的地址
- history.replaceState(data, title, url)
- popstate 事件: 监听地址的改变
手动的进行
pushState()
并不会触发popstate
事件。点击浏览器前进后退时候触发。
<div id="div1">
<ul>
<li><a id="a1">s0</a></li>
<li><a id="a2">k0</a></li>
</ul>
</div>
var div1 = document.getElementById('div1');
var a1 = document.getElementById('a1');
var a2 = document.getElementById('a2');
var count1 = 0;
var count2 = 0;
history.replaceState({ count1: count1, count2: count2 }, null, ''); //最开始的状态,采用replace直接替换
a1.addEventListener('click', function() {
count1++;
history.pushState({ count1: count1, count2: count2 }, null, '#/s' + count1); //之后的状态,需要进行保存
a1.innerHTML = 's' + count1;
});
a2.addEventListener('click', function() {
count2++;
history.pushState({ count1: count1, count2: count2 }, null, '#/k' + count2); //之后的状态,需要进行保存
a2.innerHTML = 'k' + count2;
});
window.addEventListener('popstate', function(e) {
console.log(e.state);
a1.innerHTML = 's' + e.state.count1; //监听popstate事件,对状态进行还原
a2.innerHTML = 'k' + e.state.count2;
});