javascript – 为什么在加载iframe时在Safari中没有触发popstate?

在Safari中,如果存在iframe加载,并且用户通过返回或转发更改历史记录状态,则不会触发popstate事件,从而导致应用程序状态和窗口位置不同步.

我认为一个活跃的XHR请求会导致相同的行为,但我还没有确认.

这是一个允许您轻松重现问题的jsfiddle:
http://jsfiddle.net/neonsilk/muHk8/

您只需按顺序单击链接/按钮,从1到6.

在Safari 5.0.5中,输出为:

(反向按时间顺序排列,重要的部分是顶部的状态比较)

[1305665493096] /
[1305665493096] vs
[1305665493096] /node
---------------
[1305665489955] iframe loaded
---------------
[1305665489806] (did popstate or $.address change trigger?)
[1305665489805] called history.back()
[1305665489805] appended iframe
---------------
[1305665488428] popstate: /node
[1305665488427] $.address change: /node
---------------
[1305665487821] popstate: /
[1305665487821] $.address change: /
---------------
[1305665487179] $.address change: /node
---------------
[1305665486606] $.address change: /
---------------
[1305665485732] iframe loaded
---------------
[1305665485569] $.address change: /neonsilk/muHk8/show/
[1305665485568] $.address init

然而在Chrome(11)或FireFox(4.0)中,输出如下:

(注意状态是同步的)

[1305665609499] /
[1305665609499] vs
[1305665609499] /
---------------
[1305665608360] iframe loaded
---------------
[1305665607770] popstate: /
[1305665607770] $.address change: /
[1305665607758] (did popstate or $.address change trigger?)
[1305665607758] called history.back()
[1305665607758] appended iframe
---------------
[1305665606870] popstate: /node
[1305665606869] $.address change: /node
---------------
[1305665606150] popstate: /
[1305665606149] $.address change: /
---------------
[1305665605551] $.address change: /node
---------------
[1305665604808] $.address change: /
---------------
[1305665603354] iframe loaded
---------------
[1305665602688] $.address change: /neonsilk/muHk8/show/
[1305665602682] $.address init
[1305665602676] popstate: /neonsilk/muHk8/show/

这是Safari中的错误吗?如果是的话,是否有人发现了一种解决方法?

(同样有趣的是,FireFox和Chrome都会在页面加载时触发popstate事件.)

最佳答案 更新

据我所知,这个错误是first reported by Ben Cherry.

这是WebKit的相应bug reportchangeset.

the issue from Chromium.

我无法弄清楚Chrome中修复错误的时间.如果有其他人,我会非常感谢这些信息.

我知道WebKit 533.21.1中存在这个bug(这是Safari 5.0.5使用的),并且已经被534.36(Safari / WebKit nightly)修复了 – 但是我不知道,并且还没有能够弄清楚,哪个中间构建引入了修复.

有一个a helpful chart将Chrome版本映射到其WebKit版本.

最重要的是,当存在任何活动的网络流量(图像加载,Ajax请求等)而不仅仅是iframe时,这个错误就会发生.如果您正在尝试实现History API支持,或者您使用的是最新版本的Asual’s jQuery Address plugin(默认情况下启用了历史记录支持),则此错误可能会严重影响您的应用程序.

第二次更新

我想我已经找到了引入修复程序的确切WebKit版本(534.10).所以,如果您使用的是jQuery和Asual的Address插件,这里是实用的解决方案:

if (!($.browser.webkit === true && parseFloat($.browser.version) < 534.10)) {
    // only enable state support if WebKit version >= 534.10
    $.address.state("/base/path");
}

我希望这可以帮助别人!

我刚刚在最新的WebKit中测试了小提琴(r86671),状态保持同步,所以它一定是个bug.有趣的是,花费大量时间撰写问题并立即提交问题会激发答案.

不过,如果有人有解决方法,我们将不胜感激.

WebKit每晚(r86671):

[1305666598481] /
[1305666598481] vs
[1305666598480] /
---------------
[1305666597469] iframe loaded
---------------
[1305666597300] popstate: /
[1305666597298] $.address change: /
[1305666597270] (did popstate or $.address change trigger?)
[1305666597269] called history.back()
[1305666597269] appended iframe
---------------
[1305666596605] popstate: /node
[1305666596605] $.address change: /node
---------------
[1305666596008] popstate: /
[1305666596008] $.address change: /
---------------
[1305666595555] $.address change: /node
---------------
[1305666595142] $.address change: /
---------------
[1305666578600] iframe loaded
---------------
[1305666578400] $.address change: /_display/
[1305666578400] $.address init
---------------
[1305666577964] popstate: /_display/

同样有趣的是,Safari现在可以匹配Chrome和FireFox的行为,在页面加载时激活popstate.

点赞