历史API是否在iOS上被破解? (位置栏不在pushState上更新)

归档这个下我无法相信没有人注意到这之前或我必须失踪的东西类别:

看来,如果你在iOS上做了一个简单的window.history.pushState ,那么位置栏不会更新,除非它是响应用户的手势。 状态本身确实被推动(正如你通过点击后退button所看到的)。

这是最小的testing案例,我可以想出重现这个问题:

http://thelink.is/history-api-ios-bug

在支持History API的桌面浏览器上,您应该会看到地址栏中的URL每秒都会变为/ 0,/ 1等。 在iOS上 – 使用iPhone(运行iOS 4.3)和iPad(运行iOS 4.3.3)进行testing – 地址栏不更新,但点击后退button将带您正确的以前的位置(这将在testing案例404没有后端逻辑来处理这些URL)。

思考? 解决方法? 一个肩膀哭泣,拥抱?

更新:这个问题已在iOS 5中修复。

所以最重要的是,iOS已经在历史API的基础上增加了自己的安全性,这意味着你不能使用脚本来改变URL。 只有用户操作才能允许历史loggingAPI根据Aral的示例更改url – 即点击。

解决方法是在URL上使用散列(aka片段标识符)。

而不是history.pushState我们只是改变位置:

 var i = 0; var locationUpdateInterval = setInterval(function(){ window.location.hash = i; i++; }, 1000); 

要捕捉事件,无论是在iOS应用程序中更改该位置,还是在应用程序的某个特定页面/面板上都有永久链接:

 // named function on purpose for later function hashchange() { var pageId = location.hash.substr(1); // drop the # symbol // do something with pageId } window.onhashchange = hashchange; // onload - if there's a hash on the url, try to do something with it if (location.hash) hashchange(); 

我们不能在iOS上使用pushState / popState ,但是它的安全性与无法触发全屏video相同,除非用户启动操作,这与在iOS上下载video或audio内容相同 -不能编写脚本,用户必须启动它(不知何故)。

就像关于Android的说明一样 – 问题是非常相似的,所以这(应该)也作为Android的解决方法。

如果你想桌面支持,大多数浏览器支持onhashchange但是,你猜,IE是缺乏 – 所以你可以polyfill那个坏男孩(虽然需要jQuery …): http : //benalman.com/projects/jquery -hashchange-插件/

希望有所帮助。

使用时适用于我: https : //github.com/browserstate/history.js – 这也修复了许多其他跨浏览器错误与HTML5的历史API。

从v1.7开始,下面是它解决的错误:

  • History.js 解决了以下浏览器错误:
    • HTML5浏览器
      • Chrome 8有时在返回到初始状态时不包含正确的状态数据
      • Safari 5,Safari iOS 4和Firefox 3和4在页面加载散列时不会触发onhashchange事件
      • 与其他浏览器不同,Safari 5和Safari iOS 4在散列发生变化时不会触发onpopstate事件
      • 一旦散列被replaceState调用/ 错误报告replace,Safari 5和Safari iOS 4将无法返回到正确的状态
      • Safari 5和Safari iOS 4有时无法在繁忙条件/ 错误报告中应用状态更改
      • 一旦页面加载/ 更改build议 ,RC之前的Google Chrome 8,9,10和Firefox 4将始终启动onpopstate
      • Safari iOS 4.0,4.1,4.2有一个工作的HTML5历史API–尽pipe浏览器的实际后退button不起作用,因此我们将它们视为HTML4浏览器
      • HTML5浏览器没有实际使用pushStatereplaceState调用的title参数
    • HTML4浏览器
      • 像MSIE 6,7和Firefox 2之类的旧浏览器没有onhashchange事件
      • 即使有人告诉MSIE 6和7有时也不会应用散列(要求第二次调用apply函数)
      • 非哈希HTML4浏览器有时不会应用散列,当哈希没有urlencoded
    • 所有浏览器
      • 状态数据和标题在站点被留下然后返回时不会持续(包括页面刷新)
      • 状态标题从不应用于document.title

(更新:刚刚看到雷米也是这么回答的 – 请看上面的他的深入答案)。

Remy在Twitter上为这个问题提供了一个解决方法 。

基本上,如果您更改了location.hash,则位置栏中的地址会更新。 但是,这确实在历史中创build了一个单独的条目(这不适用于我试图实现的目标)。 我正在实施的解决方法是在iOS中使用hash-bang URL,在其他平台上使用常规的URL,直到修复了iOS错误。 这绝对是不理想的,我希望iOS上的移动Safari能够像桌面上的Chrome,Firefox和Safari一样运行。

这是我发现的:

当推送位置包含散列符号时,地址栏将被更新。 所以这将工作:

 window.history.pushState(data, title, 'a/new/url#'); 

但是window.location对象不会被更新,所以如果你需要推送的位置,你需要将推送的url保存到一个variables中,并使用它来代替window.location。

testingAndroid的Safari。

我发现了一个有点工作的黑客。 事实certificate,如果您在history.pushState之后更改了散列,地址栏会被更新。 喜欢:

  window.history.pushState(data, title, 'a/new/url'); window.location.hash = 'new'; 

将地址栏更改为http://example.com/a/new/url#new 。 这引入了另一个问题,因为哈希变成了自己的历史logging。 所以你需要听取onHashChange。

这有点复杂,但也有一些人真的非常讨厌hashbang网站,并且对此非常不满。 所以这是值得的。

Interesting Posts