前端实现路由的两种方式浏览器页面跳转是通过后台实现的,自从前后端分离,前端也把路由跳转给接管了,就是说url的改变不发送给服务器,而是让浏览器自己处理,这样有一个好处可以减轻服务器的压力,一般适用于SPA。
目前实现前端路由有两种方式,一种是hash,一种是用history api
hash路由
hash路由实现的原理是通过监听window的hashchange
事件,来做响应更新页面处理
hash即URL中"#"字符后面的部分,有以下特点
- hash值不会随着请求发送给服务器
- hash改变不会导致重新加载页面
监听hash值改变
window.addEventListener('hashchange', () => {
// ...路由跳转
}, false);
hash的读写
可以通过location.hash
来读写hash值
hash路由优缺点
优点:兼容低版本浏览器
缺点:不美观,会和锚点冲突
history api
hash路由虽然可以满足前端路由跳转,但是不太美观,history api可以解决这个问题,让url看起来跟原来服务器直接跳转方式没什么区别
length:history栈中的记录数
back():返回上一页
forward():前进下一页
go(number|url):参数为负数返回,正数前进,history.go(1)相当于history.forward()
html5提供两个新的方法pushState()
和replaceState()
以及一个全局监听事件popstate
pushState
history.pushState(state, title, url)
在history栈添加新记录
使用pushState()可以改变referrer,在用户发送XMLHttpRequest请求时会在HTTP头部的referrer会响应的改变,因为referrer是标识创建XMLHttpRequest对象时this所代表的window对象中document的URL
假设在http://localhost:8080/index.html
中执行了以下代码:
var state = { id: 123 };
history.pushState(state, null, "a.html");
地址会变成http://localhost:8080/a.html
,但是页面不会加载a.html
replaceState
replaceState(state, title, url)
是在history栈替换当前的记录,参数和效果与pushState类似
popstate事件
每当处于激活状态的history栈发生变化时,popstate事件就会在对应window对象上触发,但是注意的是pushState和replaceState不会触发popstate事件
popstate事件只会在浏览器某些行为下触发, 比如浏览器后退、前进按钮,js代码里的history.back(),history.go(),history.forward(),location.hash
history.pushState({ id: 1 }, null, '?page=1');
history.pushState({ id: 2 }, null, '?page=2');
history.replaceState({ id: 3 }, null, '?page=3');
history.back();
此时的url是http://localhost:8080/a.html,触发了popstate事件,event对象的state值为{id: 1}
history.state
页面加载时,或许会有个非null的状态对象。这是有可能发生的,举个例子,假如页面(通过pushState()或 replaceState()方法)设置了状态对象而后用户重启了浏览器。那么当页面重新加载时,页面会接收一个onload事件,但没有popstate事件。然而,假如你读取了history.state属性,你将会得到如同popstate被触发时能得到的状态对象。
兼容低版本浏览器history api库,提供了跟history一样接口写法
hash和history的区别
模式 | 优点 | 缺点 |
---|---|---|
hash | 使用简单、无需后台支持 |
|
history | 地址美观,便于理解 | 需要后台或者服务器配合刷新跳转 |