Javascript history pushState onpopstate方法做AJAX SEO

news/2024/5/14 0:04:01/文章来源:https://blog.csdn.net/weixin_34191845/article/details/93714851
参考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
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari
replaceState, pushState54.0 (2.0)1011.505.0
history.state184.0 (2.0)1011.506.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。不过如果你觉得这个#!很好看就没关系了。

twtter hash

新的解决方案: 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_703640.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自学python推荐书籍同时找哪些来实践-Python学习路上有这些论坛、网站、书籍与你同行...

Python学习路上有这些论坛、网站、书籍与你同行 2019-05-03 18:24:41 613点赞 9508收藏 164评论 创作立场声明:希望我的一些经验可以给你少走一些弯路,但人总得走点弯路才可以成长。别怕,在学习python的路上有我陪着你。人生苦短,…

怎么在python下载网站内容-分析某网站,并利用python自动登陆该网站,下载网站内容...

本帖最后由 愤怒的小车 于 2019-5-8 09:41 编辑 一:本代码是我研究了好久才写出来,七功能主要有自动登陆、自动识别验证码、以及自动识别下载格式进行判断下载! 首先,搬上我们的主角网址,http://lavteam.org/&#xff…

python爬虫怎么爬同一个网站的多页数据-不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据...

原标题:不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据Python爬虫为什么受欢迎 如果你仔细观察,就不难发现,懂爬虫、学习爬虫的人越来越多,一方面,互联网可以获取的数据越来越多,另一方面…

切换节点服务器网站,服务器手动切换节点

服务器手动切换节点 内容精选换一换1、集群当前的节点数较多,可以选择将部分节点进行删除,对集群进行缩容操作以同时节省费用。2、集群中某个节点出现异常且无法手动恢复后,可使用节点删除将该节点进行删除操作,随后根据需要再重新…

网站访问过程理解(一点记录)

一个普通网站访问的过程 简单概括一下,对于我们普通的网站访问,涉及到的技术就是:用户操作浏览器访问,浏览器向服务器发出一个 HTTP 请求;服务器接收到 HTTP 请求,Web Server 进行相应的初步处理&#xff0…

【错误记录】GitHub 网站和仓库无法访问 ( 域名重定向 | 检查 C:\Windows\System32\drivers\etc\hosts 配置文件中的 GitHub 地址域名配置 )

文章目录一、报错信息二、解决方案一、报错信息 在家里的电脑中 , 出现 无法访问 GitHub 网站 , 使用任何手段都无法访问 GitHub ; 二、解决方案 家里的电脑比较乱 , 使用了各种游戏加速器 , 梯子等工具 , 另外为了解决某些特定问题 , 手动修改 C:\Windows\System32\drivers\et…

SEO优化简要工作流程

SEO技术是复杂的,知识体系也是非常庞大的,但是知识相比实战技巧,知识就显得次要了。SEO初学者往往重知识,却往往忽视其中的技巧,实战技巧也绝非短期内可积累到的。本人其实也是一个SEO新手,虽然有6-7年做站…

webzip下载整个网站工具-WebZip

2019独角兽企业重金招聘Python工程师标准>>> WebZip 把一个网站下载并压缩到一个单独的 ZIP 文件中,也可以下载到你电脑的文件夹当中,可以帮您将某个站台全部或部份之资料以ZIP格式压缩起来,可供你日后快速浏览这个网站。且新一版的功能包括可…

网站自动登录功能的设计[转]

网站的自动登录一直都是有利于提高用户体验的功能,如果设计不好,也非常容易泄漏用户的账户信息。 比较常见的功能实现方案是将用户的登录信息保存在浏览器的Cookie中。看到一些设计有缺陷的网站会将用户的用户名和密码信息保存在Cookie中,这种…

如何用python创建一个下载网站-用Python下载一个网页保存为本地的HTML文件实例...

我们可以用Python来将一个网页保存为本地的HTML文件,这需要用到urllib库。 比如我们要下载山东大学新闻网的一个页面,该网页如下:实现代码如下: import urllib.request def getHtml(url): html urllib.request.urlopen(url).read…

如何用python创建一个下载网站-用Python下载一个网页保存为本地的HTML文件实例...

我们可以用Python来将一个网页保存为本地的HTML文件,这需要用到urllib库。 比如我们要下载山东大学新闻网的一个页面,该网页如下:实现代码如下: import urllib.request def getHtml(url): html urllib.request.urlopen(url).read…

自学python推荐书籍同时找哪些来实践-Python学习路上有这些论坛、网站、书籍与你同行...

Python学习路上有这些论坛、网站、书籍与你同行 2019-05-03 18:24:41 613点赞 9508收藏 164评论 创作立场声明:希望我的一些经验可以给你少走一些弯路,但人总得走点弯路才可以成长。别怕,在学习python的路上有我陪着你。人生苦短,…

怎么在python下载网站内容-分析某网站,并利用python自动登陆该网站,下载网站内容...

本帖最后由 愤怒的小车 于 2019-5-8 09:41 编辑 一:本代码是我研究了好久才写出来,七功能主要有自动登陆、自动识别验证码、以及自动识别下载格式进行判断下载! 首先,搬上我们的主角网址,http://lavteam.org/&#xff…

python爬虫怎么爬同一个网站的多页数据-不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据...

原标题:不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据Python爬虫为什么受欢迎 如果你仔细观察,就不难发现,懂爬虫、学习爬虫的人越来越多,一方面,互联网可以获取的数据越来越多,另一方面…

白帽社区“乌云”已超9小时无法访问 公告称网站服务升级

7月20日,国内知名白帽子社区“乌云”(http://www.wooyun.org/)今日已无法正常访问,网站挂出公告称“进行升级”。 7月19日晚间23点,微博“互联网的那件事”曝出乌云官方网站显示无法访问。由此算来,截至发稿…

网站发布

转载于:https://www.cnblogs.com/defineconst/p/6380324.html

增长黑盒:零代码基础做智能电商网站,不要重复发明轮子

增长黑盒:零代码基础做智能电商网站 Step0,不破不立,走上增长黑客之路 很多卖货的人最大的问题就是整个团队没有一个懂代码的,更不懂电商网站制作。此时贸然出去外包一个电商网站,问题可能会越来越多。 《增长黑客》中…

【校园先行者】曲径通幽,我用阿里云部署的个人网站及挂机实践分享

未见意趣,必不乐学。目前大二的田程,出于对软件编程的爱好用ECS云服务器部署了一个个人网站。最初使用虚拟机服务的他,认为阿里云服务器的高性价比、丰富的云市场以及详备的售后完美满足了个人需求。 项目初衷 我叫田程,是四川理工…

借助URLOS快速安装python3网站环境

环境需求 1. 最低硬件配置:1核CPU,1G内存(11)提示:如果你的应用较多,而主机节点的硬件配置较低,建议在部署节点时开通虚拟虚拟内存;2. 生产环境建议使用2G或以上内存;3. …

免费猪八戒网站软件任务小助手--小八戒更新版本1.5

前段时间猪八戒网站改版了,我把小八戒也更新了一下,以适应他们新的版面。 界面还是那样,没有做其它的更改。其实本来打算做出来2.0之后再发布的,但是因为这段时间太忙,没有时间去开发2.0,就先把1.5放出来了…