如何跨多个 iframe(同一域)创建点击事件?

How to create click event across MULTIPLE iframes (same domain)?

我有一个主(父)页面,其中托管了同一域下的 3 个 iframe。将 iframe 的 src 属性添加到单击事件中,因此只有在需要时才会加载 iframe。

我想要的是当我点击主页上的某个 div 时,它会同时触发对位于所有 3 个 iframe 内的特定 div 的点击。

我在我的父页面中尝试了以下代码:

function myFunction() {
  var iframe = document.getElementById("iframe1");
  var elmnt = iframe.contentWindow.document.getElementById("btn").click()
}

并为 iframe 的 #iframe2#iframe3 重复了两次。但是,除非我加载 iframe 以便将它们写在我的页面上,否则它不起作用。 (即 #iframe2 上的点击事件直到 #iframe1 的事件之后才执行)。这是一个问题,因为我无法控制 iframe 访问者将首先加载的内容。我尝试给它们单独的 function() 名称,但同样的事情发生了——一次只影响一个 iframe。请注意,当我使用 iframe 进行测试时效果很好,因为 iframe 的 src 已经正常,只是在手动添加时不行。

我也试过在 iframe 页面中添加这个:

parent.document.getElementById('btn').onclick = function(){
 document.getElementById('btn').click();
}

但是,这仅适用于加载的第一个 iframe(即,如果首先加载 #iframe2,则 iframe1iframe3 的事件将不会执行)

我可以尝试其他解决方案吗?我的目的是用 classList.toggle 创建一个白天和黑夜的切换,我希望所有 iframes css 使用切换按钮同时切换 在主页上。

(我更喜欢主页上的原版 javascript,但 iframe 页面上的 jQuery 没问题)

你正在动态加载 iframe 的 src 假设用户加载 <iframe3> 但你的代码是这样写的,它试图在 <iframe1> 中用 <div> 做一些事情(这不是尚未加载)会发生什么?它会抛出错误并中断执行,这就是为什么它不适合您的原因您需要的是首先查看它们当前是否存在 你也在使用 var iframe = document.getElementById("iframe1"); 但我在你发布的 fiddle 上没有看到任何 ID

试试这个

<body>

<style>
body {
  background:#fff;
  color:#000
}

body.toggled 
{
    background:#000;
    color:#fff
}
</style>

<div id="btn">click here to toggle css</div>
<p>page content</p>

<a href="/iframe1" target="iframe1">add src to iframe one</a><br>
<a href="/iframe2" target="iframe2">add src to iframe two</a><br>
<a href="/iframe3" target="iframe3">add src to iframe three</a>

<p>iframe 1:</p>
<iframe src="about:blank" id="iframe1" name="iframe1"></iframe>

<p>iframe 2:</p>
<iframe src="about:blank" id="iframe2" name="iframe2"></iframe>

<p>iframe 3:</p>
<iframe src="about:blank" id="iframe3" name="iframe3"></iframe>
</body>

<script>

    document.querySelector('#btn').addEventListener('click', function(e) {
    [].map.call(document.querySelectorAll('body,a'), function(el) {
     el.classList.toggle('toggled');
    });


    var iframe1 = document.getElementById("iframe1");
    var iframe1btn = iframe1.contentWindow.document.getElementById("btn");
    if(iframe1btn) //<-- check if that element really exists within <iframe>
        iframe1.contentWindow.document.getElementById("btn").click()
    // you could've also used <iframe>'s loaded event but this is better way

    var iframe2 = document.getElementById("iframe2");
    var iframe2btn = iframe2.contentWindow.document.getElementById("btn");
    if(iframe2btn)
        iframe2.contentWindow.document.getElementById("btn").click()

    var iframe3 = document.getElementById("iframe3");
    var iframe3btn = iframe3.contentWindow.document.getElementById("btn");
    if(iframe3btn)
        iframe3.contentWindow.document.getElementById("btn").click()

});

</script>

我不是特别确定你错在哪里,但我想我明白你想做什么。要重现此示例,请在您的本地 PC 中创建一个 HTML 文件(名称为 index.html),并在您的浏览器中创建 运行 此文件:

<!DOCTYPE html>
<html>
  <head>
    <style>
      body {
        background: #fff;
        color: #000;
      }


      body.toggled {
        background: #000;
        color: #fff;
      }
    </style>
  </head>
  <body>
    <div id="btn">click here to toggle css</div>
    <p>page content</p>

    <a href = "" target="iframe1">add src to iframe one</a><br>
    <a href = "" target="iframe2">add src to iframe two</a><br>
    <a href = "" target="iframe3">add src to iframe three</a>

    <p>iframe 1:</p>
    <iframe src="about:blank" name="iframe1"></iframe>

    <p>iframe 2:</p>
    <iframe src="about:blank" name="iframe2"></iframe>

    <p>iframe 3:</p>
    <iframe src="about:blank" name="iframe3"></iframe>

    <script>
      let outerBody = document.querySelector('body')
      let toggleButton = document.querySelector('#btn')
      let iframes = document.querySelectorAll('iframe')
      let anchors = document.querySelectorAll('a')

      toggleButton.addEventListener('click', () => {
        let body = document.querySelector('body')
        body.classList.toggle('toggled')
        Array.from(iframes).forEach(iframe => {
          toggleIframe(iframe)
        })    
      })

      Array.from(iframes).forEach(iframe => {
        iframe.addEventListener('load', e => {
          toggleIframe(iframe)
        })
      })

      Array.from(anchors).forEach(anchor => {
        anchor.addEventListener('click', e => {
          let targetedIframe = document.querySelector(`iframe[name=${anchor.target}]`)
          targetedIframe.src = './index.html'
        })
      })

      function toggleIframe(iframe) {
        let iframeBody = iframe.contentWindow.document.querySelector('body')
        let iframeToggleButton = iframe.contentWindow.document.querySelector('#btn')
        let isOuterBodyToggled = outerBody.classList.contains('toggled')
        let isIframeBodyToggled = iframeBody.classList.contains('toggled')

        if (isOuterBodyToggled && iframeToggleButton && !isIframeBodyToggled)
          iframeToggleButton.click()
        else if (!isOuterBodyToggled && iframeToggleButton && isIframeBodyToggled)
          iframeToggleButton.click()
      }
    </script>
  </body>
</html> 

我将您的 ahref 更改为空 (#)。我还更改了您的 JS 文件。基本上,我指定了 as 以在用 addEventListener('click') 单击它时更改其关联的 iframe 的来源。此外,每次我通过单击 iframes' 按钮来单击 outerBody's (parent browsing context) button, I will also toggle its containing iframes' 正文。那已经有效了。但是,您的问题是您不知道 iframes 何时加载。 iframes 上有一个函数 addEventListener('load')。当加载 iframe 时(iframe 将在其源更改时再次加载),我将使用该事件侦听器来检查其父浏览上下文的主体是否已切换。如果是,那么也可以通过单击来切换 iframe 的正文。

瞧,它起作用了。如前所述,请尝试将上面的代码粘贴到您 PC 的本地文件中,然后 运行 在浏览器中粘贴它。