区别
hash模式下,仅hash符号之前的内容会被包含在请求中,如 http://www.11.com 因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误;
history模式下,前端的url必须和实际后端发起请求的url一致,如http://www.222.com/aa/ 。如果后端缺少对/aa/ 的路由处理,将返回404错误。此时需要在后端作出相应的调整(比如nginx配置重定向)
hash模式
hash就是指url后的#号以及后面的字符。
hash也称作锚点,本身是用来做页面定位的,他可以使对应的id元素显示在可视区域内。
hash模式背后的原理是 onhashchange
事件,可以在window对象上监听这个事件,并通过window.hash 获取 url 后面的hash值。
window.onhashchange = function(event){
console.log(event.oldURL, event.newURL);
let hash = location.hash.slice(1);
// 获取hash后可以用来进行下一步的操作
document.body.style.color = hash;
}
hash发生变化的url都会被浏览器记录下来,所以浏览器的前进后退都可以用了,以上代码点击前进后退时,页面字体颜色也会发生变化。这样一来,尽管浏览器没有请求服务器,但是页面状态和url一一关联起来,后来人们给它起了一个霸气的名字叫前端路由,成为了单页应用标配。
history模式
利用了html5 History 中新增的 pushState 和 replaceState 方法。这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。
pushState 和 replaceState 方法
pushState 用来在浏览器历史中添加记录,replaceState 用来在浏览器历史中修改当前记录。当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
pushState 方法
history.pushState方法接受三个参数,依次为:
- state:一个与指定网址相关的状态对象,popstate 事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null。
- title:新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null。
- url:新的网址,必须与当前页面处在同一个域(不能跨域!!)。浏览器的地址栏将显示这个网址。
// 假定当前网址是example.com/1.html
// 我们使用pushState方法在浏览记录(history对象)中添加一个新记录。
var stateObj = { foo: 'bar' };
history.pushState(stateObj, 'page 2', '2.html');
添加上面这个新记录后,浏览器地址栏立刻显示example.com/2.html,但并不会跳转到2.html,甚至也不会检查2.html是否存在,它只是成为浏览历史中的最新记录。
假定这时你访问了其他页面,然后点击了倒退按钮,页面的url将显示2.html,但是内容还是原来的1.html。你再点击一次倒退按钮,url将显示1.html,内容不变。
replaceState 方法
history.replaceState方法的参数与pushState方法一模一样。
// 假定当前网页是example.com/example.html。
history.pushState({page: 1}, 'title 1', '?page=1');
history.pushState({page: 2}, 'title 2', '?page=2');
history.replaceState({page: 3}, 'title 3', '?page=3'); // 修改了当前页面page=2
history.back()
// url显示为http://example.com/example.html?page=1
history.back()
// url显示为http://example.com/example.html
history.go(2)
// url显示为http://example.com/example.html?page=3
popstate 事件
每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件,但是调用 pushState 和 replaceState 方法不会触发改时间,只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。
使用的时候,可以为 popstate 事件指定回调函数。这个回调函数的参数是一个event事件对象,它的state属性指向 pushState 和 replaceState 方法为当前URL所提供的状态对象(即这两个方法的第一个参数)。
window.onpopstate = function (event) {
console.log('location: ' + document.location);
console.log('state: ' + JSON.stringify(event.state));
};
// 或者
window.addEventListener('popstate', function(event) {
console.log('location: ' + document.location);
console.log('state: ' + JSON.stringify(event.state));
});