本博客不欢迎:各种镜像采集行为,请尊重知识产权法律法规。大家都是程序员,不要闹得不开心。
在前端框架层出不穷的当今时代,页面的变化变得更加具有迷惑性。页面地址变了的话,是否就意味着一定请求了新的页面么?在h5时代之前,答案是肯定的,肯定请求了新的页面。但是在h5时代全面展开后,这个论断就值得怀疑了,眼见不一定为实。页面地址变化了,但是很有可能浏览器并没有请求服务器。那么,在本文中,苏南大叔就描述的是:如何才能不刷新页面,同时还能够改变URL的方式方法。
前端路由实现:通过pushState()改变URL,同时不刷新页面(图6-1)
本文测试环境:mac/[email protected]。
基本前提
这里描述一下本文中的相关代码的使用前提:那就是不支持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
前端路由实现:通过pushState()改变URL,同时不刷新页面(图6-2)
另外,本文中的方法,都是定义在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()改变URL,同时不刷新页面(图6-3)
上边这个代码中,先pushState()一次,然后replaceState()一次。那么,第一次真实页面请求,生成了一条历史记录,然后,pushState()生成了第二条历史记录,replaceState()再把第二条历史记录进行了替换。最终的效果是这样的。
前端路由实现:通过pushState()改变URL,同时不刷新页面(图6-4)注意:当pushState()或replaceState()后,因为url通常发生了变化,而且并没有请求服务器,是个假冒的地址请求过程。如果这个时候,再次f5刷新后,就会真实的页面请求。所以,页面很有可能会发生较大变化!要有这个心理预期!毕竟pushState()或replaceState()的地址显示,只是个虚假的演示效果!
特别注意referer来源
这个pushState()和replaceState()方法改变页面地址后,这个页面上发出的下一次请求,对应的referer数据也会发生变化。这个不做详细说明,大家看图即可。
前端路由实现:通过pushState()改变URL,同时不刷新页面(图6-5)
前端路由实现:通过pushState()改变URL,同时不刷新页面(图6-6)
总结
通过pushState()和replaceState()方法改变URL的方法,在一些高级前端框架里面,是非常常见的。由于篇幅限制,那么本文中,苏南大叔主要描述的是URL的变化,这些push进去的数据,如何pop出来,将在下一篇文字中描述,敬请期待。
更多h5新函数应用,可以参见苏南大叔的h5系列文章:
如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。