我可以在iframe中使用window.location.replace吗?


15

我们可以使用它window.location.replace避免历史记录,定位页面锚,而无需重新加载页面,不能在iframe中使用吗?

问题是违反CSP(内容安全策略),script-src 'unsafe-inline'必须启用该状态。除非我没有定义CSP,即使我定义了一个CSP并允许script-src 'unsafe-inline'它仍然给出相同的违规错误。在ie11 / chrome / ff中得到相同的结果。

iframe位于同一域(位于同一目录中)。

  1. 在控制台中定位iframe并在控制台中使用window.location.replace('/samepage.html#onpage_anchor')
  2. 有用。 它以页面锚为目标,而无需重新加载页面和历史记录。
  3. 将相同的代码内联在锚链接上,它可以工作。
  4. 外部脚本中使用相同的代码获取csp违规错误。 如果不在iframe中,则效果很好。

我试图创建一个CSP允许的动作,但即使是最宽松的内容安全策略可能会允许它。


编辑:所以我将示例放到允许多个文件的插件上,这样我就可以使用引用父/子页面的正确hrefs。

有关示例的示例的注释:

  1. 这些示例中未重现该问题。 该脚本即使在iframe中也可以完美运行。但是,相同的代码在我的本地服务器上不起作用,或者当我在VPS上实时运行该代码时。

  2. 我怀疑在plunker上不会触发CSP违规,因为plunker通过某种抽象层将内容呈现给浏览器。

  3. 第一次单击父级中的手风琴链接时,它会刷新。这是因为页面最初加载的方式没有引用index.html。后续点击将按预期工作,而无需重新加载页面。在iframe中这不是问题,因为它最初会引用child.html

  4. 这些是显示代码而无需进行任何更改即可使其工作的很好的示例(如需要更改href使其在stackoverflow代码段中工作,如下所述)。这也很好,因为它显示了javascript应当正常工作。但这并没有显示出实际的问题。您仍然需要在编辑器中加载它,然后在本地服务器或实时托管环境中运行它,才能看到真正的问题。

柱塞示例

有脚本: 无历史记录
无脚本: 有历史记录


简化的代码示例

一键输入的简单手风琴。足以重现问题。

单击打开/关闭将展开/折叠手风琴,不需要JS。JS应该做完全相同的事情,但是没有历史记录。工作正常,但不能在iframe中使用。

代码段注释:

  1. 您可以运行该代码段以了解我所描述的内容,但实际上并不能证明问题所在。

  2. 该代码段的行为与实际浏览器中的行为不同,JavaScript无法正常工作。

  3. 该代码段显示了代码,但应在iframe中运行以查看问题。在iframe外部运行它,以查看差异以及其工作原理。

  1. 由于链接如何与JS配合使用(替换整个url),因此它们实际上必须像这样,href="https://stackoverflow.com/thispage.html#ac1"而不是 href="#ac1"像它们出现在代码段中一样(不能以代码段中的实际html页面为目标)。因此,如果您在编辑器中尝试此操作 (请这样做),请记住将链接更改为此格式, this_document.html#anchor以使它们仍然是相同的页面定位点,但是page.html包含在链接中。


剧本

$(document).ready(function() {

      // anchor links without history
      $.acAnch = function(event) {
        event.preventDefault();
        var anchLnk = $(event.target);
        var anchTrgt = anchLnk.attr('href');
        window.location.replace(anchTrgt);
      }
      // listen for anchor clicks
      $('.accordion').on('click', 'a', $.acAnch);

    });

这非常简单:
1. acAnch函数采用该href属性并将其放入window.location.replace()
2.监听手风琴中的锚点,以运行acAnch功能。

这样所有脚本都可以运行 window.location.replace('/this_same_page.html#on_page_anchor')

如果将其放在控制台中,它将起作用,并且不会违反CSP。但是从外部脚本运行它不起作用。

内联在链接上工作正常:

onclick="event.preventDefault();window.location.replace('/thispage.html#acc0');"
onclick="event.preventDefault();window.location.replace('/thispage.html#acc1');"

将其放在相应的链接上效果很好,但是我真的不喜欢使用内联脚本。必须有一种使用外部脚本执行此操作的方法

我尝试在父级而不是iframe上运行javascript(当然可以通过修改来选择子级中的链接)。相同的CSP错误结果。


我为什么要这样做?

好吧,该站点比示例要复杂得多。iframe中的锚可以正常工作,但可以添加历史记录。如果您在没有javascript的情况下运行上述代码(或仅运行了代码段),请打开和关闭手风琴几次,然后使用“后退”按钮,它将返回到打开关闭状态。

我不介意历史记录,但是如果它在iframe中,则当您离开父页面然后返回到它时,iframe中的历史记录将被破坏。回溯不再返回所有手风琴状态,而是继续重新加载iframe。最初,锚点不会导致iframe重新加载,而只是逐步浏览手风琴状态历史记录,效果很好,直到您离开页面并返回。然后返回就不再经过手风琴状态,而只是经过一堆相同的iframe重新加载。这是非常用户不友好的行为。

如果有另一种方法可以使用,我不需要使用location.replace。我尝试了许多其他方法,但发现可以达到相同结果的方法通常会导致相同的错误。

目标只是激活页面上的锚点链接,而无需 在iframe中重新加载且没有历史记录

内联脚本有效。我们可以使其在外部.js文件中工作吗?


您是否只是在寻求锚点?如果是这样,<a href="#ac0" class="ac-close">Close</a>应该可以。
Dementic '19

好的,我在plunker上设置示例。不幸的是,该问题并未在插棒上再现。相反,该脚本即使在iframe中也可以正常工作。有脚本-没有历史记录没有脚本有历史记录。次要的小问题;父级上的手风琴链接会导致页面刷新,只有在第一次单击时才会进行刷新(最初是在没有index.html参考的情况下加载,因此,在第一次单击后,它会按预期运行,而不会重新加载页面)。对于iframe来说,这不是问题,因为它已加载了child.html src。
Veneseme Tyras,

因此,至少通过小插曲示例,您可以看到完整的代码并查看其工作方式。但是,它不能在我的本地服务器上运行,也不能在VPS上实时运行。我将使用插件链接和信息更新问题。
Veneseme Tyras,

1
我将您的示例代码带到服务器上,它运行正常,然后从您的示例plnkr.co/edit/V3kx7LQbTppaQ6V06uZp?p=preview创建了一个新的plunker示例,它也运行正常。没有CSP错误结果。
思想家

是的,在我也做过的pl子上效果很好。不过,我很好奇它在您的服务器上的工作方式,因为在您发表评论后,我进行了三遍检查,但无法在实时服务器或本地服务器上使用它。
Veneseme Tyras,

Answers:



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.