如何在 DOM 中移动 iFrame 而不丢失其状态?

IT技术 javascript jquery dom iframe
2021-02-08 08:25:10

看看这个简单的 HTML:

<div id="wrap1">
  <iframe id="iframe1"></iframe>
</div>
<div id="warp2">
  <iframe id="iframe2"></iframe>
</div>

比方说,我想提出的面纱,以便#wrap2将之前#wrap1iframe 被 JavaScript 污染了。我知道 jQuery.insertAfter().insertBefore(). 但是,当我使用它们时,iFrame 会丢失所有的 HTML 以及 JavaScript 变量和事件。

假设以下是 iFrame 的 HTML:

<html>
  <head>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
      // The variable below would change on click
      // This represents changes on variables after the code is loaded
      // These changes should remain after the iFrame is moved
      variableThatChanges = false;
      $(function(){
        $("body").click(function(){ 
          variableThatChanges = true; 
        });
      });
    </script>
  </head>
  <body>
    <div id='anything'>Illustrative Example</div>
  </body>
</html>

在上面的代码中,variableThatChanges如果用户点击身体,变量会...改变。此变量和点击事件应在 iFrame 移动后保留(以及已启动的任何其他变量/事件)

我的问题如下:使用 JavaScript(使用或不使用 jQuery),我如何移动 DOM(及其 iframe 子项)中的 wrap 节点,以便 iFrame 的窗口保持不变,并且 iFrame 的事件/变量/等保持不变相同的?

6个回答

不可能在不重新加载的情况下将 iframe 从 dom 中的一个位置移动到另一个位置。

这是一个示例,表明即使使用本机 JavaScript,iFrame 仍会重新加载:http : //jsfiddle.net/pZ23B/

var wrap1 = document.getElementById('wrap1');
var wrap2 = document.getElementById('wrap2');
setTimeout(function(){
    document.getElementsByTagName('body')[0].appendChild(wrap1);
},10000);
DelightedD0D,赏金是由@djechlin 开启的——“我想知道这在 2016 年是否仍然如此”,看看过去 5 年关于这个问题是否有任何变化。您可以在我的回答中查看有关这些年变化的摘要。
2021-03-20 08:25:10
好吧,如果 iFrame 重新加载,那么它不是一个选项。
2021-03-22 08:25:10
是的,该示例的目的是表明即使使用本机 JavaScript,iFrame 仍会重新加载。
2021-03-25 08:25:10
如果它重新加载,这将导致它丢失 iframe 内的内容。我想你可以在使用 jquery 移动它之前抓取 iframe 内的内容,$("#iframeid").contents()但是这不会获取存储的 javascript 数据,它必须由 iframe 发送到父页面。(或者父页面必须从iframe)
2021-03-26 08:25:10
嗯,实际上,我真的不在乎它是否重新加载,因为它们的位置是about:blank,但我真正关心的是丢失框架内的内容。
2021-03-29 08:25:10

这个答案与@djechlin 的赏金有关

对 w3/dom 规范进行了大量搜索,但没有找到任何最终明确指出在 DOM 树中移动时应重新加载 iframe 的内容,但是我确实在 webkit 的 trac/bugzilla/microsoft 中找到了许多关于多年来,不同的行为发生了变化。

我希望有人能找到有关此问题的任何具体信息,但现在这是我的发现:

  1. 根据Ryosuke Niwa - “这是预期的行为”。
  2. 有一个“神奇的 iframe”(webkit,2010 年),但它在 2012 年删除
  3. 根据 MS - “ iframe 资源从 DOM 中移除时被释放”。当您appendChild(node)使用现有节点时 -node首先从 dom 中删除。
    这里有趣的事情 -IE<=8没有重新加载 iframe - 这种行为(有点)是新的(因为IE>=9)。
  4. 根据Hallvord RM Steen 的评论,这是iframe 规范中的引用

    当一个 iframe 元素被插入到一个有浏览上下文的文档中时,用户代理必须创建一个新的浏览上下文,将元素的嵌套浏览上下文设置为新创建的浏览上下文,然后对 iframe 属性进行“第一次处理” ”

    这是我在规范中找到的最接近的东西,但是它仍然需要一些解释(因为当我们iframe在 DOM 中移动元素时,我们并没有真正做一个完整的remove,即使浏览器使用该node.removeChild方法)。

将感谢downvoter 的答复和解释。
2021-03-15 08:25:10
真的希望在 dom 中有按引用传递,这样你就可以在多个位置有相同的元素
2021-03-28 08:25:10

每当附加 iframe 并应用 src 属性时,它都会触发加载操作,类似于通过 JS 创建 Image 标签。因此,当您删除然后附加它们时,它们是全新的实体,它们会刷新。它是如何window.location = window.location重新加载页面的。

我知道重新定位的唯一方法iframes是通过 CSS。这是我放在一起的一个例子,展示了一种处理这个问题的方法flex-boxhttps : //jsfiddle.net/3g73sz3k/15/

基本思想是创建一个flex-box包装器,然后使用每个 iframe 包装器上的 order 属性为 iframe 定义特定顺序。

<style>
  .container{
    display: flex;
    flex-direction: column;
  }
</style>
<div class="container">
  <div id="wrap1" style="order: 0" class="iframe-wrapper">
    <iframe id="iframe1" src="https://google.com"></iframe>
  </div>
  <div id="warp2" style="order: 1" class="iframe-wrapper">
    <iframe id="iframe2" src="https://bing.com"></iframe>
  </div>
</div>

正如您在 JS fiddle 中看到的,这些order样式是内联的以简化flip按钮,因此将iframes.

我从这个 StackOverflow 问题中获取了解决方案:仅使用 CSS 交换 DIV 位置

希望有帮助。

如此简单有效!非常感谢你!
2021-03-22 08:25:10
赏金第一段并解释它类似于 img 并创建新实体。不是 css :P
2021-03-23 08:25:10
哈利lua!我花了很长时间才找到这个,这正是我想要做的,只需重新排列框架即可。
2021-04-08 08:25:10

如果您已经在页面上创建了 iFrame 并且稍后只需移动它的位置,请尝试以下方法:

将 iFrame 附加到正文并使用高 z-index 和 top,left,width,height 将 iFrame 放在您想要的位置。

甚至 CSS 缩放也适用于身体而无需重新加载,这太棒了!

我为我的“小部件”维护了两种状态,它要么被注入到 DOM 中,要么使用这种方法注入到主体中。

当其他内容或库会挤压或挤压您的 iFrame 时,这很有用。

繁荣!

不幸的是,parentNodeHTML DOM 元素属性是只读的。当然,您可以调整 iframe 的位置,但您不能更改它们在 DOM 中的位置并保留它们的状态。

请参阅我创建的这个 jsfiddle,它提供了一个很好的测试平台。http://jsfiddle.net/RpHTj/1/

单击该框以切换值。单击“移动”以运行 javascript。