参考MDN:

https://developer.mozilla.org/zh-CN/docs/DOM/Manipulating_the_browser_history

https://developer.mozilla.org/zh-CN/docs/Mozilla_event_reference/popstate

window 对象通过history对象提供对览器历史记录的访问能力。它暴露了一些非常有用的方法和属性,让你在历史记录中自由前进和后退,而在HTML5中,更可以操纵历史记录中的数据。

历史记录概览

可以通过back(),forward()和go()方法在用户的历史记录中前进与后退。

前进与后退

在历史记录中后退,可以这么做:

window.history.back();

这就像用户点击浏览器的后退按钮一样。

类似的,你可以前进,就像在浏览器中点击前进按钮,像这样:

window.history.forward();

移动到指定的历史记录点

通过指定一个相对于当前页面位置的数值,你可以使用go()方法从当前会话的历史记录中加载页面(当前页面位置索引值为0,上一页就是-1,下一页为1)。

要后退一页(相当于调用back()):

window.history.go(-1);

向前移动一页(相当于调用forward()):

window.history.go(1);

类似的,传递参数“2”,你就可以向前移动2页。

你可以查看length属性值,了解历史记录栈中一共有多少页:

var numberOfEntries = window.history.length;
注意: IE中可以给go()方法传递URL字符串参数,这是非标准的方法,并且Gecko不支持。

添加和修改历史记录条目

HTML5引进了history.pushState()方法和history.replaceState()方法,它们允许你逐条地添加和修改历史记录条目。这些方法可以协同window.onpopstate事件一起工作。

使用 history.pushState() 会改变 referrer 的值,而在你调用方法后创建的 XMLHttpRequest 对象会在 HTTP 请求头中使用这个值。referrer的值则是创建 XMLHttpRequest 对象时所处的窗口的URL。

案例

假设 http://mozilla.org/foo.html 将执行如下JavaScript代码:

var stateObj = { foo: "bar" };
history.pushState(stateObj, "page 2", "bar.html");

这将让浏览器的地址栏显示http://mozilla.org/bar.html,但不会加载bar.html页面也不会检查bar.html是否存在。

假设现在用户导航到了http://google.com,然后点击了后退按钮,此时,地址栏将会显示http://mozilla.org/bar.html,并且页面会触发popstate事件,该事件中的状态对象(state object)包含stateObj的一个拷贝。该页面看起来像foo.html,尽管页面内容可能在popstate事件中被修改。

如果我们再次点击后退按钮,URL将变回http://mozilla.org/foo.html,文档将触发另一个popstate事件,这次的状态对象为null。回退同样不会改变文档内容。

pushState()方法

pushState()有三个参数:一个状态对象、一个标题(现在会被忽略),一个可选的URL地址。下面来单独考察这三个参数的细节:

  • 状态对象(state object) — 一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝。

    任何可序列化的对象都可以被当做状态对象。因为FireFox浏览器会把状态对象保存到用户的硬盘,这样它们就能在用户重启浏览器之后被还原,我们强行限制状态对象的大小为640k。如果你向pushState()方法传递了一个超过该限额的状态对象,该方法会抛出异常。如果你需要存储很大的数据,建议使用sessionStorage或localStorage。

  • 标题(title) — FireFox浏览器目前会忽略该参数,虽然以后可能会用上。考虑到未来可能会对该方法进行修改,传一个空字符串会比较安全。或者,你也可以传入一个简短的标题,标明将要进入的状态。

  • 地址(URL) — 新的历史记录条目的地址。浏览器不会在调用pushState()方法后加载该地址,但之后,可能会试图加载,例如用户重启浏览器。新的URL不一定是绝对路径;如果是相对路径,它将以当前URL为基准;传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。该参数是可选的;不指定的话则为文档当前URL。

注意: 在 Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) 至 Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) 中,传入的对象使用JSON来进行序列化。从 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)开始,对象使用结构化拷贝算法来进行序列化。这将允许更多类型的对象能够安全传入。

某种意义上,调用pushState()有点类似于设置window.location='#foo',它们都会在当前文档内创建和激活新的历史记录条目。但pushState()有自己的优势:

  • 新的URL可以是任意的同源URL,与此相反,使用window.location方法时,只有仅修改 hash 才能保证停留在相同的document中。
  • 根据个人需要来决定是否修改URL。相反,设置window.location='#foo',只有在当前hash值不是foo时才创建一条新历史记录。
  • 你可以在新的历史记录条目中添加抽象数据。如果使用基于hash的方法,你只能把相关数据转码成一个很短的字符串。

注意pushState()方法永远不会触发hashchange事件,即便新的地址只变更了hash。

replaceState()方法

history.replaceState()操作类似于history.pushState(),不同之处在于replaceState()方法会修改当前历史记录条目而并非创建新的条目。

当你为了响应用户的某些操作,而要更新当前历史记录条目的状态对象或URL时,使用replaceState()方法会特别合适。

注意: 在 Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) 至 Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) 中,传入的对象使用JSON来进行序列化。从 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)开始,对象使用结构化拷贝算法来进行序列化。这将允许更多类型的对象能够安全传入。

popstate事件

每当激活的历史记录发生变化时,都会触发popstate事件。如果被激活的历史记录条目是由pushState所创建,或是被replaceState方法影响到的,popstate事件的状态属性将包含历史记录的状态对象的一个拷贝。

案例见 window.onpopstate

读取当前状态

在页面加载时,可能会包含一个非空的状态对象。这种情况是会发生的,例如,如果页面中使用pushState()或replaceState()方法设置了一个状态对象,然后用户重启了浏览器。当页面重新加载时,页面会触发onload事件,但不会触发popstate事件。但是,如果你读取 history.state 属性,你会得到一个与  popstate 事件触发时得到的一样的状态对象。

你可以直接读取当前历史记录条目的状态,而不需要等待popstate事件:

var currentState = history.state;

浏览器兼容性

  • Desktop
Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
replaceState, pushState 5 4.0 (2.0) 10 11.50 5.0
history.state 18 4.0 (2.0) 10 11.50 6.0

你可能需要History.js来解决跨浏览器兼容性问题。

其他资料

  • window.history
  • window.onpopstate
如果你玩过Google+,看到过YouTube的新界面,便会体验到这个HTML5的新功能。使用pushState + Ajax(pjax),可以实现网页的ajax加载,同时又能完成URL的改变而没有网页跳转刷新的迹象,就像是改变了网页的hash(#)一样。

旧的解决方案

曾说SEO和ajax是天敌。此前从Twitter开始流行Ajax+hash的方式调用内容,Google给出的解决方案是“#!~string”自动转换为“?_excaped_fragment_=~string”来抓取动态内容。但这无疑会非常麻烦:首先你需要对网站进行“?_excaped_fragment_=~string”的处理配置,而且,如果用户把网址“http://example.com/#!/~string”直接复制并分享的话,意味着网页还必须监听hashchange。不过如果你觉得这个#!很好看就没关系了。

新的解决方案: pushState

然而HTML5的新接口pushState / replaceState就可以比较完美的解决问题,它避免了改变hash的问题,避免了用户不理解URL的形式感到疑惑,同时还有onpopstate提供监听,良好响应后退前进。而且它不需要这个URL真实存在。

HTML5 的 pushState+Ajax

HTML5提供history接口,把URL以state的形式添加或者替换到浏览器中,其实现函数正是 pushState 和 replaceState。

pushState 例子

pushState() 的基本参数是:

window.history.pushState(state, title, url);

其中state和title都可以为空,但是推荐不为空,应当创建state来配合popstate监听。

例如,我们通过pushState现改变URL而不刷新页面。

var state = ( {

url: ~href, title: ~title~additionalKEY~additionalVALUE

} );

window.history.pushState(state, ~title~href);

其中带有“~”符号的是自定义内容。就可以把这个~href(URL)推送到浏览器的历史里。如果想要改变网页的标题,应该:

document.title= ~newTitle;

注意只是pushState是不能改变网页标题的哦。

replaceState 同理

window.history.replaceState( state, ~title, ~href);

pushState、replaceState 的区别

pushState()可以创建历史,可以配合popstate事件,而replaceState()则是替换掉当前的URL,不会产生历史。

限制因素

只能用同域的URL替换,例如你不能用http://baidu.com去替换http://google.com。而且state对象不存储不可序列化的对象如DOM。

Ajax 配合 pushState 例子

现在用Ajax + pushState来提供全新的ajax调用风格。以jQuery为例,为了SEO需要,应该为a标签的onclick添加方法。

$("~target a").click(function(evt){

evt.preventDefault(); // 阻止默认的跳转操作

var uri=$(this).attr('href');

var newTitle=ajax_Load(uri); // 你自定义的Ajax加载函数,例如它会返回newTitle

document.title=newTitle; // 分配新的页面标题

if(history.pushState){

var state=({

url: uri, title: newTitle

});

window.history.pushState(state, newTitle, uri);

}else{ window.location.href="#!"+~fakeURI; } // 如果不支持,使用旧的解决方案

return false;

});

function ajax_Load(uri){ ... return newTitle; } // 你自定义的ajax函数,例如它会返回newTitle

即可完成pushState。至于新标题newTitle的获取就是另外的问题了,例如你可以为a标签分配data-newtitle=~title属性并届时读取,或者如果你用的$.ajax()函数,可以用$(result).filter("title").text()来获取。

另外如果需要对新加载的页面的连接同样使用这个ajax,则需要对新内容的a标签重新部署,例如

$("~newContentTarget a").click(function(evt){ ... });

pushState 配合 popstate 监听

想要良好的支持浏览器的历史前进后退操作,应当部署popstate监听:

window.addEventListener('popstate', function(evt){

var state = evt.state;

var newTitle = ajax_Load(state.url); //你自定义的ajax加载函数,例如它会返回newTitle

document.title=newTitle;

}, false);

提醒,你可以通过setRequestHeader()来让服务器端配合你的ajax请求输出专门的内容。

jQuery + PJAX 插件

已经在github上发布,有人把PJAX做成了jQuery插件,方便调用,节省大量代码:

if ($.support.pjax) {

$(document).on('click', 'a[data-pjax]', function(event) {

var container = $(this).closest('[data-pjax-container]')

$.pjax.click(event, {container: container})

});}

转载于:https://www.cnblogs.com/sunshq/p/4228033.html

Javascript history pushState onpopstate方法做AJAX SEO相关推荐

  1. JavaScript 学习-48.$.ajaxSetup方法设置AJAX的全局默认设置

    前言 $.ajaxSetup方法用于设置AJAX的全局默认设置.之后执行的所有AJAX请求,如果对应的选项参数没有设置,将使用更改后的默认设置. 这方便我们设置error 统一返回样式. 示例 设置全 ...

  2. html5新特性:利用history的pushState等方法来解决使用ajax导致页面后退和前进的问题

    html5新特性:利用history的pushState等方法来解决使用ajax导致页面后退和前进的问题 参考文章: (1)html5新特性:利用history的pushState等方法来解决使用aj ...

  3. ajax怎么找回地址栏,使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL...

    HTML5里引用了新的API,就是history.pushState和history.replaceState,就是通过这个接口做到无刷新改变页面URL的. 与传统的AJAX的区别 传统的ajax有如 ...

  4. 使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" ...

  5. 使用ajax和history.pushState无刷新改变页面URL

    HTML5里引用了新的API,history.pushState和history.replaceState,就是通过这个接口做到无刷新改变页面URL的. 与传统的AJAX的区别 传统的ajax有如下的 ...

  6. java pjax_GitHub - szyjava/pjax: ajax + history.pushState = pjax

    介绍 pjax是对ajax + pushState的封装,让你可以很方便的使用pushState技术. 同时支持了缓存和本地存储,下次访问的时候直接读取本地数据,无需在次访问. 并且展现方式支持动画技 ...

  7. history`pushState和window`onpopstate实现tab切换效果

    前言 先来介绍一下history.pushState()和window.onpopstate history.pushState(),改变当前地址栏的路径,并不会更新页面内容 用法:history.p ...

  8. ajax与HTML5 history pushState/replaceState实例

    一.本文就是个实例展示 三点: 我就TM想找个例子,知道如何个使用,使用语法什么的滚粗 跟搜索引擎搞基 自己备忘 精力总是有限的,昨天一冲动,在上海浦东外环之外订了个90米的房子,要借钱筹首付.贷款和 ...

  9. javascript:jquery.history.js使用方法

    javascript:jquery.history.js使用方法 step1:download jquery.history.js step2:create a test page as follow ...

最新文章

  1. sip 时序图_时序图怎么看_教你如何看懂时序图 - 什么是时序图_时序图怎么看_教你如何看懂时序图...
  2. 梁建章的多米诺,混合办公的未知数
  3. OpenCASCADE:Foundation Classes之数学原语和算法
  4. 甲骨文中国公司如何如何打赢这场裁员翻身仗?
  5. Zoom惊人财报、传苹果打造搜索引擎与谷歌竞争、Netflix部分剧集免费以吸引新用户等| Decode the Week...
  6. sringboot security基本用法
  7. 牛客假日团队赛5 F 随机数 BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数 (dfs记忆化搜索的数位DP)...
  8. android 空白占位符,android textview空格占位符以及一些其他占位符汇总
  9. 被拘捕 353 天后,三星“太子”李在镕被判缓刑当庭获释!
  10. zigzag矩阵按照之字形线路产生方法(C++)
  11. import pandas as pd什么意思_【医学名词】多发性骨髓瘤MR、SD、PD分别是什么意思?...
  12. 词法分析程序实验报告
  13. 如何在苹果Mac上右键点击?
  14. 微软切断XP供应 Vista成制造商惟一选择
  15. Docker Centos安装Openssh
  16. 短文本分类---小白从0到0.3的辛酸历程(上)
  17. 《C#之集训1-20121019c#基础》
  18. w10计算机无法启动不了怎么办,win10开不开机怎么办_win10电脑无法开机的解决步骤...
  19. Android 利用adb命令 使App自动点击屏幕指定位置
  20. 用程序哄你的小孩睡觉

热门文章

  1. Java中的初始化顺序
  2. libevent在windows下使用步骤详解
  3. 网络编程学习笔记(gethostbyname函数)
  4. Vue04 -- 计算属性用法(v-for的筛选排序)
  5. python基础作业第十四天
  6. 函数的作用域(嵌套函数的运行)
  7. linux中tomcat修改错误日志路径
  8. linux源码安装nginx
  9. ORM 和 JDBC有何不一样
  10. 推荐15款响应式的 jQuery Lightbox 插件