HTML5 History API提供了一种功能,能让开发人员在不刷新整个页面的情况下修改站点的URL。这个功能很有用,例如通过一段JavaScript代码局部加载页面的内容,你希望通过改变当前页面的URL来反应出页面内容的变化,这时该功能可以派上用场。

  举个例子,当用户从首页进入帮助页面时,我们通过Ajax来加载帮助页面的内容。然后这个用户又转到产品页面,我们需要再一次通过Ajax请求来替换页面的内容。当用户想分享页面的URL时,通过History API,我们可以改变页面的URL来反应内容的修改,这样不管是用户分享还是保存的URL都能和页面的内容对应起来。

基本知识

  要查看这个API提供了哪些功能非常简单,打开浏览器的Developer Tools工具面板,然后在console中输入history。如果你的浏览器支持History API,你将会看到这个对象下面附带了很多方法。

  注意其中的pushStatereplaceState这两个方法。我们可以在console中进行一些简单的测试,来看看当我们使用这两个方法时URL会发生什么变化。稍后我们将分析这两个方法中的所有参数,现在我们只需要关注最后一个参数:

history.replaceState(null, null, 'hello');

  上面代码中的replaceState方法改变了当前页面的URL,在后面添加了一个'/hello'。不过并没有发出任何request请求,当前窗口仍然停留在之前的页面。不过这里有个问题,当你点击浏览器的后退按钮时,页面并不会回退到我们通过replaceState方法修改之前的那个URL,而是直接回退到了上一个页面(即我们进入到这个页面之前的那个页面)。这是因为replaceState方法不会修改浏览器的history,它只是简单地替换了地址栏中的URL。

  要解决这个问题我们需要使用pushState方法:

history.pushState(null, null, 'hello');

  现在再点击浏览器的后退按钮,你会发现它和你预想的效果一样。因为pushState方法将我们传给它的URL添加到浏览器的history中,从而改变了浏览器的history。假如我们将另外一个完整的站点URL传递给它会发生什么情况呢?例如我们在baidu.com的首页进行测试,然后在console中输入下面的内容。

history.pushState(null, null, 'https://twitter.com/hello');

  浏览器会报错。因为传递给pushState方法的URl必须和当前页面的URL属于同一个源(即不能跨域),否则会有很大的安全漏洞,开发人员可能会借用该功能来欺骗用户,让他们觉得自己是在访问一个完全不同的站点,而事实并非如此。

  来看看传递给pushState方法的所有参数:

history.pushState([data], [title], [url]);

  1. 第一个参数用来传递我们需要的数据,当页面的状态发生变化时我们可以接收到该数据。如用户点击浏览器的后退和向前按钮。需要注意的是在Firefox中只允许传递最多640K的数据。
  2. 第二个参数title是一个字符串,不过截止到目前,几乎所有的浏览器都忽略该参数。
  3. 最后一个参数是我们想要替换的URL。

简单回顾一下

  这些History API最主要的功能就是不重新加载页面。以往我们只能通过改变window.location的值来修改当前页面的URL,不过这会导致整个页面被重新加载。如果你修改的只是URL中的hash,则不会导致页面被刷新。

  使用旧的hashbang方法可以改变页面的URL而不刷新页面。著名的Twitter就是使用的该方法,不过也广受诟病,毕竟hash在location中并不被作为一个真正的资源来对待。

  作为History API的早期支持者,Twitter后来抛弃了传统的hashbang方法。在2012年,Twitter的团队介绍了他们的新方法,并列出了其中的一些问题同时还详细地介绍了各浏览器应该如何实现该规范。

一个使用pushState和Ajax的例子

https://css-tricks.com/examples/State/

  在该示例中,我们希望用户通过我们的网站找到电影捉鬼敢死队(一部美国电影)中的演员。当用户选择一个图片时,我们需要在下方显示该演员对应的文字描述,同时给该图片一个被选中的效果。当点击后退按钮时,页面应该切换到上一个被选中的图片状态,同时图片下方的文字也要一并切换。当点击前进按钮时也一样。

  这里有一个效果图:

  这个示例的HTML代码非常简单:div.gallery中包含了所有的链接,每个链接里有一个图片。接下来我们放置了一个空的div.content,用来存放当演员图片被点击时显示在下放的文字。

<div class="gallery"><a href="https://cdn.css-tricks.com/peter.html"><img src="bill.png" alt="Peter" class="peter" data-name="peter"></a><a href="https://cdn.css-tricks.com/ray.html"><img src="ray.png" alt="Ray" class="ray" data-name="ray"></a><a href="https://cdn.css-tricks.com/egon.html"><img src="egon.png" alt="Egon" class="egon" data-name="egon"></a><a href="https://cdn.css-tricks.com/winston.html"><img src="winston.png" alt="Winston" class="winston" data-name="winston"></a>
</div><p class="selected">Ghostbusters</p>
<p class="highlight"></p><div class="content"></div>

  如果没有JavaScript该页面仍然可以正常工作,点击图片可以跳转到对应的页面,然后点击后退按钮也可以回到之前的页面。这是为了考虑页面的可访问行和优雅降级。

  接下来我们要添加JavaScript代码了。我们通过event propagation给div.gallery元素中的每一个link添加一个事件处理程序,像这样:

var container = document.querySelector('.gallery');container.addEventListener('click', function(e) {if (e.target != e.currentTarget) {e.preventDefault();// e.target is the image inside the link we just clicked.}e.stopPropagation();
}, false);

  在if语句中,我们获取到被选中图片的data-name属性的值,然后将'.html'添加到后面拼成一个要访问的页面地址,并将其作为第三个参数传递给pushState方法(不过在真实的例子中我们可能会在Ajax请求成功之后才会去修改URL)。

var data = e.target.getAttribute('data-name'),
url = data + ".html";
history.pushState(null, null, url);// 此处更改当前的classes样式
// 然后使用data变量的值更新
// 并通过Ajax请求.content元素的内容
// 最后再更新当前文档的title

(当然,此处我们也可以直接使用link的href属性的值)

  我将真实代码中的内容都替换成注释了,这样我们可以只关注pushState方法的使用。

  现在我们点击图片,URL和Ajax请求的内容会被自动更新,但是当我们点击后退按钮时并不会回退到之前选中的演员图片。这里我们还需要在用户点击后退和前进按钮时使用另外一个Ajax请求来更新内容,并再一次使用pushState方法来更新页面的URL。

  我们使用pushState方法中的第一个参数(其中的state)来保存状态信息:

history.pushState(data, null, url);

  上面代码中的data参数在popstate事件触发时可以被获取到。当浏览器的后退和前进按钮被点击时会触发popstate事件。

window.addEventListener('popstate', function(e) {// e.state表示上一个被点击的图片的data-attribute
});

  我们可以通过该参数传递一些我们需要的信息,例如在该示例中我们将之前选中的捉鬼敢死队的演员作为参数传递给requestContent方法,在该方法中,我们使用jQuery的load方法进行一次Ajax请求。

function requestContent(file) {$('.content').load(file + ' .content');
}window.addEventListener('popstate', function(e) {var character = e.state;if (character == null) {removeCurrentClass();textWrapper.innerHTML = " ";content.innerHTML = " ";document.title = defaultTitle;} else {updateText(character);requestContent(character + ".html");addCurrentClass(character);document.title = "Ghostbuster | " + character;}
});

  如果用户点击了演员Ray的图片,event listener会被触发,然后在pushState事件中保存图片的data属性的值。当用户点击另外一个图片,并点击了浏览器的后退按钮,此时popstate事件会被触发,从而重新加载ray.html页面。

  这意味着什么呢?当我们点击一个演员的图片然后将被更改的URL分享出去,用户访问这个URL时对应的HTML文件会被自动加载进来。这会带来一些更好的用户体验,并保证了URL和页面内容的一致性从而减少了因此而带给用户的一些困惑。

  上面的示例只是简单地通过jQuery来动态加载内容,我们当然也可以在pushState方法中传递一些更加复杂的对象。不过这个例子已经能足够说明问题并帮助我们开始学习如何使用History API的功能。我们先要学会走,然后才能跑。

下一步

  如果我们想大范围地使用这种技术,我们应该考虑使用一些专有的工具,例如pjax。 它是一个jQuery的插件,使用它可以大大提高我们同时使用Ajax和pushState方法进行开发的速度,不过它只支持那些使用History API接口的现代浏览器。

  History JS可以兼容旧浏览器,对于不支持History API接口的浏览器,它依然使用旧的URL hash的方式来实现同样的功能。

有关URLs

  这里我特别引用了Kyle Neath有关URLs的说明:

URLs是一个通用的概念,它可以工作在Firefox, Chrome, Safari, Internet Explorer, curl, wget,甚至在你的iPhone, Android以及便签纸上。它是web中的一个通用的语法。不要认为这是理所当然的。任何一个稍微懂点技术的用户都可以浏览你的应用的90%以上的部分而不用去刻意记住那些URL的结构。要实现这样的效果,你需要考虑URLs的实用性。

  这意味着不论你想要进行什么样的hacks或性能优化,作为web开发人员,你应该注重URL。而随着HTML5 History API的帮助,我们可以轻松地解决诸如上述示例中的一些问题。

常见问题

  • 将Ajax请求的地址嵌入到a标记的href属性中通常是个不错的主意。
  • 确保在JavaScript的click事件处理程序中return true,这样当有人使用中键点击或命令点击时不会导致程序被意外覆盖。

补充

  • Mozilla有关操作浏览器history的文档
  • Ajax示例集锦Dive into HTML5
  • Twitter有关pushState的实现

浏览器支持

Chrome Safari Firefox Opera IE Android iOS
31+ 7.1+ 34+ 11.50+ 10+ 4.3+ 7.1+

转载于:https://www.cnblogs.com/axl234/p/6514737.html

HTML5 History API让ajax能回退到上一页相关推荐

  1. 巧用Html5 History Api解决SPA的SEO问题

    背景 想当年,我做了一个新媒体网站项目(AIISPO,已下线).跟普通资讯网站不一样的是,老板要求PC端前台的文章阅读模式一定得是瀑布流+模态框.瀑布流指的是以瀑布流的形式将文章罗列出来,而模态框则指 ...

  2. php修改浏览器地址,HTML5 history API改变浏览器地址无需hash和刷新加载页面

    现在很多网站的前端做的非常炫,点击某个链接瞬间改变浏览器的地址栏的地址,改变的方式不是使用锚点,而是直接改变 URL,页面稍后局部加载完成.如果直接复制页面地址在新的浏览器选项卡中打开则是全部加载整个 ...

  3. Resumable.js - 基于HTML5 File API的可断点续传的文件上传插件

    http://resumablejs.com/ A JavaScript library providing multiple simultaneous, stableand resumable up ...

  4. Html5 History API解析

    浏览器前进与回退操作 在传统的浏览器中我们只能通过调用window.history对象的 forward() . back() 或 go(number|url) 方法来进行页面的前进.回退或跳转到某一 ...

  5. ajax与HTML5 history pushState/replaceState实例

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

  6. java局部刷新session过期_Ajax局部页面刷新和History API结合的陷阱

    ajax在现代网站已经得到非常普遍地应用,主要的好处大家都知道(异步加载数据,不用刷新整个浏览器,更小的数据传输尺寸).对于那些老网站或者老项目来说全盘改造成ajax并不现实,于是就有了"局 ...

  7. 「前端」History API与浏览器历史堆栈管理

    本文由尚妆前端开发工程师欲休撰写 本文发表于尚妆博客,欢迎订阅! 移动端开发在某些场景中有着特殊需求,如为了提高用户体验和加快响应速度,常常在部分工程采用SPA架构.传统的单页应用基于url的hash ...

  8. html5 history api_window.history的跳转探索

    浏览器的跳转的本质是什么,历史记录是如何运作的,在spa应用中是如何进行决策的? 简介 window.history是用来保存用户在一个会话期间的网站访问记录,并提供了相应的方法进行查询,相关属性,方 ...

  9. html5 history微信浏览器返回不刷新

    History API与浏览器历史堆栈管理: 移动端开发在某些场景中有着特殊需求,如为了提高用户体验和加快响应速度,常常在部分工程采用SPA架构.传统的单页应用基于url的hash值进行路由,这种实现 ...

  10. html5 微信返回按钮,《解决微信内置浏览器返回上一页强制刷新问题方法》(示例代码)...

    微信内置浏览器在返回上一页面,且上一页面包含AJAX代码时,页面就会被强制刷新,极度影响用户体验.而我们想要的效果是:返回上一页面时,页面还停留在原来的状态,AJAX获取到的数据还在,滚动条也在原来的 ...

最新文章

  1. 特征工程在实际业务中的应用!
  2. 我花了10个小时,写出了这篇K8S架构解析
  3. R语言使用ggpubr包的ggarrange函数组合多张结论图(水平并排组合)
  4. 深度探索linux系统虚拟化 原理与实现,深度探索Linux系统虚拟化:原理与实现
  5. MobileSpace-关于我的激情的故事
  6. linux supervisor
  7. C++/OpenCV:读取视频与调用摄像头
  8. [转贴]一个农村高考落榜生的心路历程
  9. PickerView的简单介绍
  10. 学习笔记:OMP算法(Spatially Sparse Precoding in Millimeter wave MIMO Systems)
  11. SSH隧道putty使用
  12. SSM框架---开发免费小说网站(h5+电脑端)
  13. c语言中scanf的用法
  14. 5G的落地现状与未来变局
  15. 用rankn()等概率生成1~m的通用方法
  16. 爬虫入门 ---- CSDN查看文章全部评论
  17. 【PS教程】旧照片修复技巧
  18. Slurm如何应对超大作业的NSS压力?
  19. velodyne Packet containing angle overflow, first angle
  20. 第五章 CSS美化网页元素

热门文章

  1. 282.给表达式添加运算符
  2. 逻辑斯蒂回归模型为什么用sigmoid函数
  3. 2018_09_21_生活记录_参加人工智能大会
  4. 【 2015-2016 XVI Open Cup, Grand Prix of Bashkortostan, SKB Kontur Cup Stage 2】题目总结
  5. 基础集合论 第二章 9 族
  6. 怎样在html应用样式表,html – 如何仅将CSS样式应用于文本
  7. android 7.1 灭屏,oppocolorosv7.1怎么设置息屏时钟
  8. codeforces 1041A Heist
  9. JAVA API 1.8版本文档下载( 百度网盘 )
  10. 使用ifconfig命令来看网卡的IP,但是,输入命令之后,eht0里面只有 inet6 addr 而没有 inet addr...