我在 javascript/html5 中遇到历史对象和 iframe 的问题。我写了一个简单的项目来描述我的问题:
这是一个带有 iframe 和下一步按钮的页面。每次单击下一步时,它都会加载一个带有递增计数器的新页面。但是,单击浏览器后退按钮并没有做我想做的事情。让我通过将这篇文章分成以下几个部分来解释这个问题:
- 我想达到什么
- 当前项目中的不良结果
- 发布我所有的代码
1. 我想要达到的目标
我希望用户:
- 打开一个新窗口并转到http://dktest.evermight.com/
- 单击下一页并看到一个红框淡入,并看到 url
http://dktest.evermight.com/count.html?count=0
同时出现在 iframe 和浏览器的地址栏中 - 再次单击下一页并
http://dktest.evermight.com/count.html?count=1
在 iframe 和浏览器的地址栏中查看 - 单击浏览器的后退按钮一次
http://dktest.evermight.com/count.html?count=0
,并在 iframe 和浏览器的地址栏中查看 - 单击浏览器的后退按钮一次,
http://dktest.evermight.com/
在浏览器的地址栏中看到红色框淡出
2.当前项目中的不良结果
使用我在http://dktest.evermight.com/的代码,它目前没有正确执行第 4 步和第 5 步。当我执行第 4 步时,iframe 显示http://dktest.evermight.com/count.html?count=0
,但浏览器地址栏显示http://dktest.evermight.com/count.html?count=1
. 我必须再次按下浏览器的返回按钮才能使浏览器地址栏显示http://dktest.evermight.com/count.html?count=0
。当我执行第 5 步时,红色框消失了,这很好,但地址栏仍然显示http://dktest.evermight.com/count.html?count=0
。我必须再次按下以使地址栏显示http://dktest.evermight.com/
。
3.发布我所有的代码
我的代码非常简单。您可以在http://dktest.evermight.com/上查看源代码。为了方便起见,我也会在这里发布。
索引.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
var count=0;
function clicknext()
{
$('#container').fadeIn();
$('#iframe').attr('src','count.html?count='+count.toString());
$('html title').html(count);
history.pushState({blahblah:'whatgoeshere?'},'i dont know what goes here either','http://dktest.evermight.com/count.html?count='+count);
count++;
}
function hideContainer()
{
$('#container').fadeOut();
var closeurl = 'close.html';
if($('#iframe').attr('src') != closeurl )
$('#iframe').attr('src', closeurl);
}
$(document).ready(function(){
hideContainer();
});
</script>
</head>
<body>
<div id="container" style="display:none; background:red;">
<!-- IMPORTANT
When DOM first created, the iframe.src MUST BE initialize.html
I have some code that I need to fire on that page before the rest
of this document starts
-->
<iframe id="iframe" src="initialize.html"></iframe>
</div>
<input type="button" onclick="clicknext()"; value="next page" />
</body>
</html>
关闭.html
<!DOCTYPE html>
<html>
<script type="text/javascript">
parent.hideContainer();
</script>
</html>
计数.html
我不能修改 count.html 的内容。在我的真实项目中,count.html 实际上是一个 youtube 视频,它位于我无法直接访问的服务器上。
<html>
<body>Youtube video at url <script type="text/javascript">document.write(location.href);</script></body>
</html>
初始化.html
Perform application specific functionality
任何人都可以更正我的代码以达到第 1 部分所述的第 4 步和第 5 步的结果吗?
更新 好的,根据我正在做的一些实验,我对这个问题有了更多的了解。
实验1:我尝试改变线路:
$('#iframe').attr('src','count.html?count='+count.toString());
到
$('#iframe')[0].contentWindow.location.replace('count.html?count='+count.toString());
这使我能够正确执行第 4 步。显然, contentWindow.location.replace() 不会在历史对象中创建条目。但是,这导致了与 count.html 的内容相关的一些其他问题,该内容实际上是 youtube/vimeo 内容的页面。youtube/vimeo 内容要求您通过 attr('src') 方法而不是 .contentWindow.location.replace() 加载信息。所以也许解决方案是找到一种方法让 attr('src') 不使用历史对象创建条目?
实验 2我尝试的另一个可能的解决方案是更改 attr('src') 和 history.pushState() 调用的顺序。我尝试先调用 attr('src'),然后再调用 history.pushState(),然后先调用 history.pushState(),然后再调用 attr('src')。但在这两种情况下,当我按下浏览器的后退按钮时,首先返回的是 iframe 内容。因此,我无法通过历史对象捕获传递给自己的消息以执行“双重返回”,因为历史对象中的信息在事件序列中最后可用。
实验 3我还尝试使用 History.js。它没有做任何事情来解决我上面的问题。据我所知,它的工作方式与常规历史对象完全一样。
有人还有什么我可以尝试的吗?或者建议对上述任何实验进行修改?我将进一步探讨实验 1 作为一个单独的堆栈溢出问题。