iframe

208 阅读3分钟

iframe的介绍

iframe元素会创建包含另外一个文档的内联框架(即行内框架)。可以使用iframe在页面中嵌入其他文档,例如另一个页面或者是一个视频。

注意:当站点启用了https那么使用iframe引入的页面也需要是https。

iframe 对象(相对重要的属性)

属性描述
src规定在 iframe 中显示的文档的 URL。
contentDocument返回 iframe 生成的 document 对象。
contentWindow返回 iframe 生成的 window 对象。
longDesc规定一个页面,该页面包含了有关 iframe 的较长描述。
name规定 iframe 的名称。
sandbox启用一系列对 iframe 中内容的额外限制。
scrolling规定是否在 iframe 中显示滚动条
seamless设置或返回 iframe 是否应该看起来像是包含文档的一部分(无边框或滚动条)。
srcdoc规定在 iframe 中显示的页面的 HTML 内容。

iframe 内嵌 iframe。对应的 window 对象会形成一个层次结构

  • window.frames —— “子”窗口的集合(用于嵌套的 iframe)。
  • window.parent —— 对“父”(外部)窗口的引用。
  • window.top —— 对最顶级父窗口的引用。

iframe 优缺点

优点

  • 可以增加代码的可重用 用于多个网页
  • 并行加载脚本
  • 遇到加载缓慢的第三方内容如图标和广告,可以用iframe解决

缺点

  • iframe会阻塞主页面的onload事件
  • iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载
  • iframe会不利于搜索引擎优化(SEO)
  • 兼容性差

通信

postMessage

postMessage() 方法用于安全地实现跨源通信

发送消息 用 postMessage

otherWindow.postMessage(message, targetOrigin, [transfer])

  • otherWindow 其他窗口的一个引用,比如 iframe 的 contentWindow 属性、执行 window.open 返回的窗口对象、或者是命名过或数值索引的 window.frames。
  • message 将要发送到其他 window的数据。
  • targetOrigin 指定哪些窗口能接收到消息事件,其值可以是 *(表示无限制)或者一个 URI。
  • transfer 可选,是一串和 message 同时传递的 Transferable 对象。这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

接收消息 监听 "message" 事件

接收程序有一个事件监听器,监听 "message" 事件,同时我们要验证消息来源地址,以确保是个可信的发送地址。

window.addEventListener('message', function (e) {
  alert(e.origin) // 消息源的 URI(可能包含协议、域名和端口),用来验证数据源。
  alert(e.source) // 消息源,消息的发送窗口/iframe。
  alert(e.data) // 发送过来的数据。
}

####举个🌰

// a.html
<body>
  <div>
    <input id="text" type="text" value="suhonny" />
    <button id="sendMessage">发送消息</button>
  </div>
  <iframe loading="lazy" id="receiver" src="https://localhost:8807/b.html" width="400" height="400">
    <p>你的浏览器不支持 iframe。</p>
  </iframe>
  <script>
    window.onload = function () {
      // 拿到 iframe 的 window 对象
      const receiver = document.getElementById('receiver').contentWindow;
      const btn = document.getElementById('sendMessage');
      btn.addEventListener('click', function (e) {
        e.preventDefault();
        let val = document.getElementById('text').value;
        // receiver.postMessage("Hello " + val, "*"); 可以用 * 不限制
        receiver.postMessage("Hello " + val, "https://localhost:8807");
      });
    }
  </script>
</body>

// b.html
<body>
  <div id="Message">Hello csc!</div>
  <script>
    window.onload = function () {
      var Ele = document.getElementById('Message');
      window.addEventListener('message', function (e) {  // 监听 message 事件
        if (e.origin !== "https://localhost:8807") return false // 验证消息来源地址
        Ele.innerHTML = e.origin + e.data;
      });
    }
  </script>
  </script>
</body>

注意点:正确的文档在 iframe.onload触发时就位。但是,只有在整个 iframe 和它所有资源都加载完成时iframe.onload才会触发 因此在iframe资源加载完成前 不能进行其他操作

小知识

关于iframe中的cookie

  1. iframe 嵌套,每层都互相跨域的页面,最内层的依然可以访问最外层的 cookie
  2. domain相同时,跨窗口的cookie的值会发生覆盖 cookie 也受 domain 的影响。如果cookie 的 domain不一致则不能互相访问、修改;

获取 iframe 的 window 对象的另一个方式

  1. 通过索引获取:window.frames[0] —— 文档中的第一个 iframe 的 window 对象。
  2. 通过名称获取:window.frames.iframeName —— 获取 name="iframeName" 的 iframe 的 window 对象。