前端路由实现:通过pushState()改变URL,同时不刷新页面
发布于 作者:苏南大叔 来源:程序如此灵动~在前端框架层出不穷的当今时代,页面的变化变得更加具有迷惑性。页面地址变了的话,是否就意味着一定请求了新的页面么?在h5
时代之前,答案是肯定的,肯定请求了新的页面。但是在h5
时代全面展开后,这个论断就值得怀疑了,眼见不一定为实。页面地址变化了,但是很有可能浏览器并没有请求服务器。那么,在本文中,苏南大叔就描述的是:如何才能不刷新页面,同时还能够改变URL
的方式方法。
本文测试环境:mac
/chrome@73.0.3683.103
。
基本前提
这里描述一下本文中的相关代码的使用前提:那就是不支持file://
这样的协议,必须是http(s)://
这样的协议。也就是说:双击本地的html
文件打开的时候,会报错。这里先埋下个伏笔,因为这个问题,导致了后续的一系列变化。这里就是根源所在。
Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'file:///code/sunan/weui/test/bar.html' cannot be created in a document with origin 'null' and URL 'file:///code/sunan/weui/test/test.html'.
at file:///code/sunan/weui/test/test.html:12:17
另外,本文中的方法,都是定义在js
的window.history
对象上面的。所以,大家可以自行脑补上window.history.
相关字样。
pushState()
和replaceState()
参数
pushState()
和replaceState()
,因为这两个函数方法的参数,是完全一致的。所以,这里苏南大叔合并讲解描述相关参数。共需要三个参数,分别是: 一个状态对象, 一个标题 (目前被忽略), 一个URL(可选) 。(下方参数文字基本上来自官方说明,略有改动)
- 状态对象 ― 状态对象
state
是一个JavaScript
对象,通过pushState()
创建新的历史记录条目。无论什么时候用户导航到新的状态,popstate
事件就会被触发,且该事件的state
属性包含该历史记录条目状态对象的副本。 - 标题 ― 目前忽略这个参数,但是未来可能会用到。在此处传一个空字符串应该可以安全的防范未来这个方法的更改。或者,你可以为跳转的
state
传递一个短标题。 URL
― 该参数定义了新的历史URL
记录。注意,调用pushState()
后浏览器并不会立即加载这个URL
,但可能会在稍后某些情况下加载这个URL
,比如在用户重新打开浏览器时。该参数是可选的,缺省为当前URL
。
本文中的权威文字说明,来自下面的链接:
关于参数,苏南大叔友情提示您:
URL
也会有跨域相关问题,新的url
和当前的url
,必须是同一个域下的,才能正常执行。虽然官方写着URL
是可选的,但是,大多数情况下,使用最多的确实这个可选的第三个参数,而不是前两个。title
参数,目前来看,是没!用!的! 似乎没有啥地方用的到,而且如果你真的需要记录title
的话,苏南大叔建议您放到state
对象里面。后续的时候,是可以拿到数据的!
pushState()
方法
pushState()
方法,会在浏览器历史中添加新的记录,而且并不会刷新页面。下面苏南大叔示例一下可能的两种使用方式:
姿势一
三个参数如上所述,大多数情况下,最有可能发生的pushState()
的使用姿势是:
window.history.pushState(null, null, "/path.html");
也就是说,忽略state
和title
,就传个新的地址就好了。有些诡异吧?
姿势二
那么下面的使用方式,是当初的函数设计人员所期待的使用姿势:
window.history.pushState({foo: "bar"}, "title", "/path.html");
replaceState()
方法
replaceState()
方法,会替换当前浏览器历史中的记录,也并不会刷新页面。三个参数同上所示,其使用姿势如下:
姿势一
window.history.replaceState(null, null, "/path.html");
姿势二
window.history.replaceState({foo: "bar"}, "title", "/path.html");
效果展示
上边这个代码中,先pushState()
一次,然后replaceState()
一次。那么,第一次真实页面请求,生成了一条历史记录,然后,pushState()
生成了第二条历史记录,replaceState()
再把第二条历史记录进行了替换。最终的效果是这样的。
注意:当pushState()
或replaceState()
后,因为url
通常发生了变化,而且并没有请求服务器,是个假冒的地址请求过程。如果这个时候,再次f5
刷新后,就会真实的页面请求。所以,页面很有可能会发生较大变化!要有这个心理预期!毕竟pushState()
或replaceState()
的地址显示,只是个虚假的演示效果!
特别注意referer
来源
这个pushState()
和replaceState()
方法改变页面地址后,这个页面上发出的下一次请求,对应的referer
数据也会发生变化。这个不做详细说明,大家看图即可。
总结
通过pushState()
和replaceState()
方法改变URL
的方法,在一些高级前端框架里面,是非常常见的。由于篇幅限制,那么本文中,苏南大叔主要描述的是URL
的变化,这些push
进去的数据,如何pop
出来,将在下一篇文字中描述,敬请期待。
更多h5
新函数应用,可以参见苏南大叔的h5
系列文章:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。