重新加载 IFRAME 而不添加到历史记录
Posted
技术标签:
【中文标题】重新加载 IFRAME 而不添加到历史记录【英文标题】:Reload an IFRAME without adding to the history 【发布时间】:2010-10-23 17:02:19 【问题描述】:我正在更改 IFRAME 的 src
以重新加载它,它工作正常并在其 html 加载时触发 onload
事件。
但它在历史记录中添加了一个条目,这是我不想要的。有什么方法可以重新加载 IFRAME 而又不影响历史记录?
【问题讨论】:
我猜问题是后退按钮在实际转到上一页之前实际上会在 iframe 中循环。 不管它做什么,我都不想添加任何历史记录,或者有什么方法可以删除最新的历史记录?? 【参考方案1】:你可以使用javascriptlocation.replace
:
window.location.replace('...html');
将当前文档替换为 一个在提供的 URL。这 与 assign() 方法的区别是 使用 replace() 后,当前 页面不会保存在会话中 历史,这意味着用户不会 能够使用返回按钮 导航到它。
【讨论】:
这不是针对页面本身吗?我只想重新加载 IFRAME,我无法控制在加载的文档中运行的脚本。 只需将“window”替换为对您的 iframe 的引用即可。 为什么没那么简单? var ifr = document.getElementById("iframeId"); ifr.location.replace(ifr.src); 尝试使用window.frames['frame_name'].location
你也可以使用iframe.contentWindow.location.replace(href);
【参考方案2】:
就像 Greg 上面所说的, .replace() 函数就是如何做到这一点的。我似乎不知道如何回复他的答案*,但诀窍是引用 iFrames contentWindow 属性。
var ifr = document.getElementById("iframeId");
ifr.contentWindow.location.replace("newLocation.html");
*刚刚得知我需要更多声望才能对答案发表评论。
【讨论】:
【参考方案3】:使用 replace() 只是您自己的域 iframe 的一个选项。它无法在远程站点上工作(例如:twitter 按钮),并且需要一些特定于浏览器的知识才能可靠地访问子窗口。
相反,只需删除 iframe 元素并在同一位置构建一个新元素。只有在 src
属性在 DOM 中之后修改它时才会创建历史记录项,因此请确保在追加之前设置它。
编辑:JDandChips 正确地提到您可以从 DOM 中删除、修改和重新附加。不需要构建新鲜的。
【讨论】:
虽然这个答案比公认的答案更新了 2 年,但它是在不添加浏览器历史记录的情况下更改 iframe URL/src 的正确方法。出于安全原因,window.frames[frameName].location 和/或 history.replaceState 的任何其他组合都不能在 iframe 中使用。即使在同一个域上(正如我刚刚发现的那样)。 这是我尝试过的最佳工作答案。解决了我的问题。 解决方案就是这个!我需要创建 iframe,以便历史记录保持不变。 很好的答案。我试图添加带有 iframe 和 Angular 的 vimeo 嵌入视频,如下所示:<div ng-repeat="item in ct.items"><iframe src="item.url"></iframe></div>
。碰巧在 angular 设置 iframe url 之前,html 尝试使用错误的 url 加载 iframe,例如 item.url
,结果是 iframe 的 src 更改了,导致浏览器历史记录问题!解决方案是稍后使用 jquery 创建 iframe,在 angular 渲染完所有内容之后。
如果从 iframe 本身内部更改 url 是否也会出现此问题(例如,如果用户单击或 J.S. 重定向到 iframe 内的第二页)?我不直接通过 DOM 更改 iframe src。例如:我的 SPA 中的 iframe 中嵌入了一个 AdobeEsign 页面,该页面重定向到同一 iframe 中的感谢页面(然后感谢页面将 windows.postmessage 发送回我的主框架,以便我可以关闭 iframe)。 ..但此时单击我的 SPA 中的浏览器后退按钮似乎想要“离开页面”(我的 window.beforeunload 事件在用户离开 SPA 时触发)。【参考方案4】:
尝试使用此功能将旧 iframe 替换为从旧 iframe 复制的新 iframe:
function setIFrameSrc(idFrame, url)
var originalFrame = document.getElementById(idFrame);
var newFrame = document.createElement("iframe");
newFrame.id = originalFrame.getAttribute("id");
newFrame.width = originalFrame.getAttribute("width");
newFrame.height = originalFrame.getAttribute("height");
newFrame.src = url;
var parent = originalFrame.parentNode;
parent.replaceChild(newFrame, originalFrame);
像这样使用它:
setIFrameSrc("idframe", "test.html");
这种方式不会将 iframe 的 URL 添加到浏览器历史记录中。
【讨论】:
这很方便。谢谢!【参考方案5】:另一种重新创建 iframe 的方法是从 DOM 中删除 iframe,更改 src 然后重新添加它。
在很多方面,这类似于 replace()
的建议,但是当我尝试使用 History.js 并手动管理状态时遇到了一些问题。
var container = iframe.parent();
iframe.remove();
iframe.attr('src', 'about:blank');
container.append(iframe);
【讨论】:
我真的很喜欢这个:结果证明它比创建一个新的 iframe 要容易得多,因为您不需要将所有属性复制到新的 iframe(id、大小、样式类、. ..) 很棒的发现。在 Bootstrap 模式窗口中加载 iframe 内容的情况下,此解决方案对我有用。当模态框关闭时,使用回调将其删除,然后将其添加回来。修复后退按钮问题。$(modal).one('hidden.bs.modal', function() $(modal_iframe).attr('src', 'about:blank').addClass('d-none'); var modalParent = $(modal_iframe).parent(); $(modal_iframe).remove(); $(modalParent).append($(modal_iframe)); );
【参考方案6】:
一种解决方案是使用object
标签而不是iframe
标签。
替换这个:
<iframe src="http://yourpage"/>
通过这个:
<object type="text/html" data="http://yourpage"/>
将允许您在不影响历史记录的情况下更新data
属性。如果您使用诸如 React.js
之类的声明性框架,您不应该执行任何命令式命令来更新 DOM,这将非常有用。
有关iframe
和object
之间差异的更多详细信息:Use of Iframe or Object tag to embed web pages in another
【讨论】:
同意@JBE 的好答案,这对我使用 Angular2 有很大帮助,并且没有 iframe src 更改触发历史更新。 这对我不起作用。我在 Chrome 中。即使销毁 iframe 并用对象替换它仍然会导致该死的浏览器历史状态(这是没有意义的,因为被销毁的对象永远不会取回它的内容)。 Grrrrrrrrrr。【参考方案7】:最简单快速的加载方案
加载页面或框架时使用window.location.replace
不更新历史记录。
对于链接,它看起来像这样:
<a href="#" onclick="YourTarget.location.replace ('http://www.YourPage.com');">
The targeted Link</a>
或
<a href="javascript:YourTarget.location.replace ('http://www.YourPage.com');">
The targeted Link</a>
但是如果您不希望它从链接执行,而是在加载框架时自动执行,那么您应该从 iframe 将其放入 iframe 文件正文部分:
onload="window.location.replace ('http://www.YourPage.com');"
如果由于某种原因 onload 未在 iframe 中加载,则将目标框架名称而不是 window 放在如下语法中:
onload="YourTarget.location.replace ('http://www.YourPage.com');"
注意:对于此脚本,所有 onclick
、onmouseover
、onmouseout
、onload
和 href="javascript:"
都可以使用。
【讨论】:
【参考方案8】:使用replace
方法绕过将 iframe 的 URL 添加到历史记录:
HTML:
<iframe id="myIframe" src="#"></iframe>
JavaScript:
var ifr = document.getElementById('mIframe')
if (ifr)
ifr.contentWindow.location.replace('http://www.blabla.com')
【讨论】:
【参考方案9】:JDandChips 答案在跨源 iframe (youtube) 上为我工作,这里是 vanilla JS(没有 JQuery):
const container = iframe.parentElement;
container.removeChild(iframe);
iframe.setAttribute('src', 'about:blank');
container.appendChild(iframe);
【讨论】:
【参考方案10】:@JDandChips 上面有一个很好的答案,但是语法应该从 parent() 更新为 parentElement:
var container = iframe.parentElement;
iframe.remove();
iframe.attr('src', 'about:blank');
container.append(iframe);
【讨论】:
欢迎来到 ***!如果答案基本上是正确的,并且真的只需要小幅更新,您应该suggest an edit 回复答案,而不是自己发布一个新答案。如果您的建议被接受,它会给您一个badge :)以上是关于重新加载 IFRAME 而不添加到历史记录的主要内容,如果未能解决你的问题,请参考以下文章