SPA需要在不刷新页面的情况下做页面更新的能力,这就需要引入前端路由,实际上,前端路由是利用了浏览器的hash或history属性。
hash :
hash (url中#后面的部分)虽然出现在 URL 中,但不会被包含在 http 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
当hash改变时,会触发hashchange事件,监听该事件,对页面进行更新。
window.onhashchange = function() {
document.getElementById("demo").innerHTML = x; //更新页面内容
......
};
history :
history 利用了 html5 history interface 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器记录栈,
在当前已有的 back、forward、go 基础之上,它们提供了对历史记录 修改的功能(pushState将传入url直接压入历史记录栈,replaceState将传入url替换当前历史记录栈)。
只是当它们执行修改时,虽然改变了当前的 URL ,但浏览器不会立即向后端发送请求。
pushState()、replaceState() 方法接收三个参数:stateObj、title、url
history.pushState({color: "red"}, "red", "red");//设置状态
window.onpopstate = function(event) { //监听状态
if(event.state && event.state.color === "red") {
document.body.style.color = "red"; //更新页面内容
}
}
// 改变状态 *在使用history API改变浏览器的url时,仍需要额外的步骤去触发 popstate 事件,例如调用 history.back() 和 history.forward() 等方法
history.back();
history.forward();
history 对比 hash
优势:
pushState 设置的 url 可以是同源下的任意 url ;而 hash 只能修改 # 后面的部分,因此只能设置当前 url 同文档的 url。
pushState 设置的新的 url 可以与当前 url 一样,这样也会把记录添加到栈中;hash 设置的新值不能与原来的一样,一样的值不会触发动作将记录添加到栈中。
pushState 通过 stateObject 参数可以将任何数据类型添加到记录中;hash 只能添加短字符串。
pushState 可以设置额外的 title 属性供后续使用。
劣势:
history 在刷新页面时,如果服务器中没有相应的响应或资源,就会出现404。因此,如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
hash 模式下,仅 # 之前的内容包含在 http 请求中,对后端来说,即使没有对路由做到全面覆盖,也不会报 404。