history API
history API
history对象表示当前窗口首次使用以来用户的导航历史记录,history对象不会暴露用户已经访问过的URL,但是会提供一些API来实现URL的前进和后退。
URL跳转
window.history
提供三个API来实现页面URL的跳转:
go():传递一个整数,正整数表示向前跳多少,负整数表示向后跳多少。
forward():向前跳一页,类似浏览器的前进按钮。
back(): 向后跳一页,类似浏览器的回退按钮。
例如:
还可以通过查看长度属性的值来确定的历史堆栈中页面的数量:
window.history.length;
可以用这个属性来判断你的页面是否是用户第一个打开的页面:
更新URL但不进行跳转
history API
history.pushState
随着前端技术的不断发展,传统的URL跳转API已经不能在满足我们的需求了,例如在SPA应用中,页面跳转本质上并非是向服务器请求新的页面,而是通过JavaScript、DOM API等技术直接由前端改变页面内容,这个时候就需要一种能够实现可以更新URL,但是不需要进行跳转的技术。
HTML5 引入了 history.pushState()和 history.replaceState()方法,它们分别可以添加和修改历史记录条目。他们和前面讲到的go、replace等API很相似,但是最大的区别是这两个方法只会改变URL,不会向服务器发送页面请求。Vue-Router的history模式底层就是使用的这种方法。
history.pushState()和 history.replaceState()方法接收三个参数:
状态对象:状态对象 state 是一个 JavaScript 对象,通过 pushState () 创建新的历史记录条目。无论什么时候用户导航到新的状态,popstate 事件就会被触发,且该事件的 state 属性包含该历史记录条目状态对象的副本。状态对象的大小是有限制的,通常是500KB~1MB以内,如果超过这个限制就会报错。如果你需要更大的空间,建议使用
sessionStorage
以及localStorage
。标题,目前没有实现,可以传个空字符串。
URL:要跳转的URL,可以是相对路径URL,也可以是一个绝对路径URL,但是新 URL 必须与当前 URL 同源。
history.pushState()和 history.replaceState()方法的区别在于前者是新建一个历史记录,而后者是替换当前的历史记录。
window.onpopstate
每当活动的历史记录项发生变化时, popstate
事件都会被传递给 window 对象。如果当前活动的历史记录项是被 pushState
创建的,或者是由 replaceState
改变的,那么 popstate
事件的状态属性 state
会包含一个当前历史记录状态对象的拷贝。
注意 调用
history.pushState()
或者history.replaceState()
不会触发popstate
事件。popstate
事件只会在浏览器某些行为下触发,比如点击后退按钮(或者在JavaScript 中调用history.back()
方法)。即,在同一文档的两个历史记录条目之间导航会触发该事件。
history.state
history.state
可以获取到当前历史记录的状态对象,如果当前没有使用过pushState
或者replaceState
,则该属性返回null。
刷新
使用history.pushState
和history.replaceState
时需要格外注意,当用户点击刷新按钮时页面重新加载,此时浏览器仍然会发送当前URL的http请求到服务器,因此使用这两个API时需要考虑到服务端对这些GET 请求的处理,你可以
在服务端为每个URL设置一个真实的URL地址,返回对应的页面。
将所有URL都指向index.html文件(SPA)
如果你用过vue-router的history模式,那么你应该就有过这种体验,如果你没有配置好服务端,那么当你在某个URL刷新时,会得到一个404的页面,而解决的方法是在服务端为该应用的所有路径都配置返回index.html文件,这背后的原理就是其底层使用的正是history.pushState
。
示例
下面示例中实现了三个按钮,其中pushState每点击一次都会执行一次history.pushState({a: a})
,变量a初始等于0,每次使用都会+1,点击replaceState会执行history.replaceState({a: a})
,点击back按钮时会执行history.back()
函数以实现历史记录的回退,这会触发popState
事件,此时你应当可以在控制台看到事件对象(event)。
https://codesandbox.io/s/history-state-4hqci3?file=/index.html
location.hash
另一种能更新URL但不会进行跳转的方法是使用window.location.hash
。window.location
对象保存了当前URL中的各项信息,例如hostname、protocol、port和hash等属性,其中hash属性中保存了当前URL以’#’开头的URL片段,并且更新这部分片段浏览器不会发送新的http请求。
location.hash的一个应用在于页内跳转锚点,例如
当点击该链接时,页面会跳转到对应id的元素上,但是不会发送请求重新加载页面。
window.location.hash
属性可以被修改,并且修改操作会将修改后的URL添加到历史记录中,以便能够实现前进和后退。
和history API类似,location.hash也具有相应的事件监听器:hashchange。
要注意的是,和前面的popstate
事件一样,当修改window.location.hash
时并不会触发hashchange
事件,只有当前进或者后退,即在两个历史记录间切换时才会触发hashchange
事件。
location.hash和history.push的区别
从某种程度来说,调用 pushState()
和 window.location = "#foo"
基本上一样,他们都会在当前的 document 中创建和激活一个新的历史记录。但是 pushState()
有以下优势:
新的 URL 可以是任何和当前 URL 同源的 URL。但是设置
[window.location](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/location)
只会在你只设置锚的时候才会使当前的 URL。非强制修改 URL。相反,设置
window.location = "#foo";
仅仅会在锚的值不是 #foo 情况下创建一条新的历史记录。可以在新的历史记录中关联任何数据。
window.location = "#foo"
形式的操作,你只可以将所需数据写入锚的字符串中。
最后更新于