前言今天在做一个Vue的搜索功能,需要从搜索结果页跳转到详情页,然后点击返回返回刚才的结果页。如果只用window.history.go(-1)当然会刷新搜索页面,当然不行。尝试了两种修改url的方法:window.location.href,拼接一个搜索键值,点击搜索,刷新页面,url变了,功能实现了,但是bug来了。。,搜索页面闪烁后进入结果页面,不跳转页面不会出现闪烁,所以当页面刷新时,会重新加载vue实例。window.location.hash,url中的#是网页中的一个位置,当读取这个url时,页面会自动滚动到锚点。此方法不会向服务器发送请求,也不会重新加载页面。能读写。阅读时,可用于判断网页状态是否发生变化;写入时,它会在不重新加载网页的情况下创建访问历史记录。添加新的API后,百度发现HTML5为window.history对象引入了两个新的API,分别是history.pushState()和history.replaceState()方法,分别可以添加和修改历史条目。这些方法通常与window.onpopstate事件一起使用。这两个API都可以更改当前url。不同的是pushState在浏览器中创建一条新的历史记录,而history.replaceState只是将当前地址替换为指定的url。HTML5新加入的historyAPI可以在不刷新的情况下改变地址栏中的链接,用AJAX完全可以不刷新跳转。它们非常有用。他们可以在不刷新页面的情况下更改URL。这个特性后来被用于单页应用如:vue-router、react-router-dom。那么下面介绍如何使用新的API。上面提到的pushState方法提供了一种“手动操作”浏览器历史记录的方法。我们可以把浏览器历史看成一个“栈”。栈是后进先出的结构。可以想象成一堆盘子。每次用户点击打开一个新的网页时,都会向其中添加一个新的板块,称为“入栈”。用户每点击一次“返回”按钮,顶板就会被带走,称为“弹出”。并且每次浏览器显示最顶层板块的内容。语法:window.history.pushState(state,title,url);执行pushState函数后,会在浏览器的历史记录中创建一条新记录,同时地址栏中的地址内容也会发生变化。它可以接收三个参数,按语法顺序:状态对象或字符串,用于描述新记录的一些特征。此参数将添加到历史记录中以备将来使用。这个参数是开发者根据自己的需要自由给定的。这个值是一个参数,后面可以通过history.state获取;表示新页面标题的字符串。目前基本上所有的浏览器都会忽略这个参数。表示新页面的相对地址的字符串。(必须和当前页面同域)简单例子:假设当前页面为renfei.org/,打开控制台,执行如下JavaScript语句:window.history.pushState({id:1,name:"profile1"},"我的个人资料","/profile/");//第一和第二个参数可以忽略设置为null后,地址栏中的地址会变成renfei.org/profile/,但是浏览器不会同时刷新页面,甚至不检测是否目标页面存在。replaceState方法有时,您想替换当前记录而不是添加新记录。两者的区别在于replaceState()修改的是当前的历史记录项,而不是新建一个。replaceState的原理和pushState是一样的。最常用的方法是:window.history.replaceState({id:1,name:"profile"},'download','download?id=1');特点:replaceState不会添加到历史中,使用history.go(-1)会跳过当前页面,相当于history.go(-2)。popstate事件当页面加载时,它可能有一个非空状态对象。当用户在页面设置状态对象(使用pushState或replaceState)后重新启动浏览器时,可能会发生这种情况。当页面重新加载时,页面会收到onload事件,但不会收到popstate事件。但是,如果你读取history.state属性,你会得到popstate事件发生后的state对象varcurrentState=history.state;//获取当前页面调用history.pushState()或history.replaceState()设置的history.pushState的state对象参数值,不触发popstate事件。popstate事件只会被浏览器的某些动作触发,例如点击后退和前进按钮(或在JavaScript中调用history.back()、history.forward()、history.go()方法)。示例:假设当前页面地址为http://example.com/index.htmlwindow.onpopstate=function(event){alert("location:"+document.location.href+",state:"+JSON.stringify(event.state));//获取history.state对象值};//绑定事件处理函数。history.pushState({page:1},"title1","?page=100");//添加并激活一个历史条目http://example.com/index.html?page=100,条目索引为1//history.stateis{page:1}history.pushState({page:2},"标题2","?page=200");//添加并激活一个历史条目http://example.com/index.html?page=200,条目索引为2history.replaceState({page:3},"title3","?page=300");//修改当前页面http://ex..?page=200的活跃历史条目为http://ex..?page=300,条目索引为3history.back();//弹出"location:http://example.com/index.html?page=100,state:{"page":1}"history.back();//弹出”位置:http://example.com/index.html,state:nullhistory.go(2);//弹出”位置:http://example.com/index.html?page=300,state:{"page":3}pushState方法和设置hash值的区别从某种意义上说,调用pushState()类似于设置window.location="#foo",都会创建并激活一个新的历史记录在当前页记录。但是pushState()有以下优点:新的URL可以是任何与当前URL同源的URL。而设置window.location仅当您仅修改哈希时才保持相同的文件。如果需要,可以在不更改URL的情况下创建历史记录。而设置window.location.hash="#foo";如果当前哈希不是#foo,只会创建一个新的历史条目。我们可以将任意数据与新的历史项目相关联。使用基于散列的方法,所有相关数据都必须编码成一个短字符串。需要注意的是,可以通过history.pushState修改网页的URL地址,通过相关代码显示和隐藏相应的界面,实现单个页面多个界面的相互操作。该方式比直接访问URL地址速度快,执行效率高,UI体验好,但会增加页面的复杂度和耦合度,根据实际情况而定,一般用于对话框弹出框.应用:全站AJAX,使浏览器抓取AJAX页面。这有什么用?一个比较常用的场景是配合AJAX。假设一个页面左边有几个导航链接,右边有内容,导航时只需要更新右边的内容,刷新整个页面无疑是一种浪费。此时我们就可以使用AJAX拉取右边的数据了。但如果这是唯一的方式,地址栏不会改变,用户不能前进或后退,不能将当前页面加入书签或与他人分享当前页面;搜索引擎也很难抓取。这时候可以使用HTML5的HistoryAPI来解决这个问题。思路:先绑定点击事件。当用户点击链接时,通过preventDefault函数阻止默认行为(页面跳转),读取链接的地址(如果有jQuery可以写成$(this).attr('href')),通过PushState将这个地址塞进浏览器历史记录,然后使用AJAX技术拉取(如果你有jQuery,可以使用$.get方法)这个地址中的真实内容,并替换当前网页的内容同时。为了处理用户的前进后退,我们监听popstate事件。当用户点击前进或后退按钮时,浏览器地址自动转换为对应的地址,同时发生popstate事件。在事件处理函数中,我们根据当前地址抓取对应的内容,然后使用AJAX拉取这个地址的真实内容并呈现出来。最后,整个过程不会改变页面标题,直接给document.title赋值即可改变页面标题。
