Skip to content

JS 父页面与 iframe 页面交互

Published: at 03:38 PMSuggest Changes

公司的项目是 JSP 写的,使用 ifream 的场景非常多。那么 iframe 页面怎么和主页面进行交互呢?

iframe 页面调用主页面的方法

主页面代码

<!DOCTYPE html>
<html>
  <script>
    function fromFrame(data) {
      alert(data);
    }
  </script>
  <body>
    <h1>The iframe element</h1>
    <iframe name="frame-id" src="./iframe.html" title="Test iframe"></iframe>
  </body>
</html>

iframe 页面代码

<!DOCTYPE html>
<html>
  <body ">
    Enter some text:
    <input
      type="text"
      name="txt"
      value="Hello"
      onchange="myFunction(this.value)"
    />

    <script>
      function myFunction(val) {
        parent.fromFrame(val);
      }
    </script>
  </body>
</html>

分析

见文档 window.parent

iframe 页面中有这样的代码,其中

parent 返回当前窗口的父窗口对象.

如果一个窗口没有父窗口,则它的 parent 属性为自身的引用.

如果当前窗口是一个 <iframe>, <object>, 或者 <frame>,则它的父窗口是嵌入它的那个窗口

function myFunction(val) {
  parent.fromFrame(val);
}

语法

var parentWindow = window.parent;

例子

if (window.parent != window.top) {
  // 至少有三层窗口
}

其他

window.frameElement 返回嵌入当前窗口的 frame 对象. window.top 返回当前窗口最顶层的父窗口.

iframe 页面向主窗口发送信息

主页面

if (window.addEventListener) {
  window.addEventListener('message', onMessage, false);
} else if (window.attachEvent) {
  window.attachEvent('onmessage', onMessage, false);
}

function onMessage(event) {
  // Check sender origin to be trusted
  if (event.origin !== 'http://example.com') return;

  var data = event.data;

  if (typeof window[data.func] == 'function') {
    window[data.func].call(null, data.message);
  }
}

// Function to be called from iframe
function parentFunc(message) {
  alert(message);
}

iframe 页面

window.parent.postMessage(
  {
    func: 'parentFunc',
    message: 'Message text from iframe.',
  },
  '*'
);

主页面对 ifream 页面进行操作

<!-- 来自同一个网站的 iframe -->
<iframe src="/" id="iframe"></iframe>

<script>
  iframe.onload = function() {
    // 可以做任何事儿
    iframe.contentDocument.body.prepend("Hello, world!");
  };
</script>

注意点:如果是跨域的话,是无法进行操作的

<iframe src="https://example.com" id="iframe"></iframe>

<script>
  iframe.onload = function() {
    // 我们可以获取对内部 window 的引用
    let iframeWindow = iframe.contentWindow; // OK
    try {
      // ...但是无法获取其中的文档
      let doc = iframe.contentDocument; // ERROR
    } catch(e) {
      alert(e); // Security Error(另一个源)
    }

    // 并且,我们也无法 **读取** iframe 中页面的 URL
    try {
      // 无法从 location 对象中读取 URL
      let href = iframe.contentWindow.location.href; // ERROR
    } catch(e) {
      alert(e); // Security Error
    }

    // ...我们可以 **写入** location(所以,在 iframe 中加载了其他内容)!
    iframe.contentWindow.location = '/'; // OK

    iframe.onload = null; // 清空处理程序,在 location 更改后不要再运行它
  };
</script>

主页面与 ifrema 页面的通信

a.com/index.html

<!DOCTYPE html>
<html>
  <body>
    <script>
      let someFunc = (t) => (document.querySelector('#test').text = t);
      window.addEventListener('message', (event) => someFunc(e.data));
    </script>
    <span id="test">This is some dummy text.</span>
    <iframe src="https://b.com/index.html"></iframe>
  </body>
</html>

b.com/index.html

<!DOCTYPE html>
<html>
  <body>
    <button id="btn">Test</button>
    <script>
      document.querySelector('#btn').addEventListener('click', (event) => {
        window.parent.postMessage('Changed text', 'http://a.com');
      });
    </script>
  </body>
</html>

主页面调用 iframe 页面的方法

主页面代码

document.getElementById('resultFrame').contentWindow.iframeFunction();

iframe 页面代码

<html>
  <head>
    <title>iframeFunction</title>
    <script type="text/javascript">
      function iframeFunction() {
        alert('iframeFunction');
      }
    </script>
  </head>
  <body>
    iframeFunction
  </body>
</html>

总结

尽量使用 window.postMessage 方法进行两个页面的通信。


Previous Post
Linux 生成 100M 测试文件
Next Post
Linux scp 命令使用教程