HTML iframe 标签

在这里插入图片描述

概述

HTML 内联框架元素 (<iframe>) 表示嵌套的 browsing context。它能够将另一个 HTML 页面嵌入到当前页面中。

简单尝试

查看实际嵌入渲染

<h2>嵌入一个站点</h2>
<iframe
  id="inlineFrameExample"
  title="Inline Frame Example"
  width="300"
  height="200"
  src="https://www.ip.top/"
></iframe>

在这里插入图片描述

每个嵌入的浏览上下文(embedded browsing context)都有自己的会话历史记录 (session history)和 DOM 树。包含嵌入内容的浏览上下文称为父级浏览上下文。
顶级浏览上下文(没有父级)通常是由 Window 对象表示的浏览器窗口。

【注意】iframe 性能问题考虑
页面上的每个 <iframe> 都需要增加内存和其他计算资源,这是因为每个浏览上下文都拥有完整的文档环境。虽然理论上来说你能够在代码中写出来无限多的<iframe>,但是你最好还是先看看这么做会不会导致某些性能问题。

属性

全局属性

link>

width

【属性-作用】指定 iframe 的宽度。

【值】

  • 无单位数值; (默认值) 300,例如:500
  • CSS 像素格式;例如: 300px
  • 百分比格式;例如:33%

height

【属性-作用】指定 iframe 的高度。

【值】同上

name

【属性-作用】 用于定位嵌入的浏览上下文的名称。

该名称可以用作 <a><form>target 属性值,
该名称可以用作 <input><button>formtarget 属性值,
还可以用作 window.open() 的 windowName 参数值。

src

【属性-作用】被嵌套的页面的 URL 地址。

【值】

  • about:blank
    可以嵌入一个 遵从同源策略的空白页。(只有 html 基本骨架)

【tip】在 Firefox(version 65 及更高版本)、基于 Chromium 的浏览器、Safari/iOS 中使用代码移除 iframesrc 属性会导致 about:blank 被载入 frame。

srcdoc

该属性是一段 HTML 代码,这些代码会被渲染到 iframe 中。如果浏览器不支持 srcdoc 属性,则会渲染 src 属性表示的内容。

其它属性,都不常用。

通信

拓展:跨域的种类

一般有2种形式的跨域:

【前后端进行的跨域请求】浏览器中,不同源的 AJAX 发送的 请求,会造成跨域问题。

【前端页面通讯形成】父子页面之间进行的DOM操作(父子窗口之间的 document 操作)。
(下面主要讲这种)

iframe 通信方式

  • 不跨域;
  • 主域相同、子域不同;
  • 主域不同;

方式1 - 不跨域

【规则】
父页面内 document.getElementById('iframe').contentWindow.document 指向当前 嵌入的子页面 文档。
子页面内 parent.document 获取父页面文档。

【示例】

[父页面l[(https://gitcode.com/fangyinggui/study_code/blob/main/html/iframe-parent.html)

<body>
  <h2>父页面</h2>
  <textarea id="message">父父父txt</textarea>
  <br />
  <button id="test">获取内容</button>

  <p>下面是 iframe 嵌入的 子页面</p>
  <iframe id="iframe" src="/html/iframe-child.html" width="500" height="300"></iframe>

  <script>
    document.getElementById('test').onclick = function () {
      console.log(
        1,
        document.getElementById('iframe').contentWindow.document.getElementById('message').value // 1 '子子子txt'
      )
    }
  </script>
</body>

[子页面l[(https://gitcode.com/fangyinggui/study_code/blob/main/html/iframe-child.html)

<body>
  <h2>子页面</h2>
  <textarea id="message">子子子txt</textarea>
  <br />
  <button id="test">获取内容</button>

  <script>
    document.getElementById('test').onclick = function () {
      console.log(111, parent.document.getElementById('message').value) // 111 '父父父txt'
    }
  </script>
</body>

方式2 - 主域相同&子域不同

【原理】
同源:当两个页面的协议、端口和域名都相同时,它们被认为是同源的。
跨域限制:不同源的页面之间进行交互会受到浏览器的同源策略限制,例如无法通过 JS 访问对方的 DOM、Cookie 等。
document.domain 可以用来部分地绕过这个限制。
具体来说,如果2个子域名拥有相同的顶级域名,可以通过将它们的 document.domain 设置为相同的顶级域名来实现跨域通信。

【场景】主域相同,子域不同的页面间通讯。

【要求】使用 document.domain 分别在这2个页面 设置为 当前域名下的 同级 或者 父级域名。

  • 不能设置为顶级域名;
  • 不可以设置为其它形式的域名;

【示例】
1、父页面;
http://fangyinggui.write.com/a.html

<body>
  <h2>父页面</h2>
  <textarea id="message">父父父txt</textarea>
  <br />
  <button id="test">获取内容</button>

  <p>下面是 iframe 嵌入的 子页面</p>
  <iframe id="iframe" src="http://fangqiqi.write.com/b.html" width="500" height="300"></iframe>

  <script>
  	document.domain = 'fangyinggui.online' // (!没有协议、端口)
    document.getElementById('test').onclick = function () {
      console.log(
        1,
        document.getElementById('iframe').contentWindow.document.getElementById('message').value // 1 '子子子txt'
      )
    }
  </script>
</body>

2、子页面
http://fangqiqi.write.com/b.html

<body>
  <h2>子页面</h2>
  <textarea id="message">子子子txt</textarea>
  <br />
  <button id="test">获取内容</button>

  <script>
  	document.domain = 'fangyinggui.online' // (!没有协议、端口)
    document.getElementById('test').onclick = function () {
      console.log(111, parent.document.getElementById('message').value) // 111 '父父父txt'
    }
  </script>
</body>

主域不同

location.hash

【原理】
1、动态改变location.hash,iframe不会重载
2、无论跨域与否,iframe内可以获取自己的 location.hash
3、只要域名相同就能通信,即使 ABC 三层嵌套

【示例】
a.html(http://www.aaa.com/demo/cross/iframe03/a.htm)嵌套了
b.html(http://www.bbb.com/demo/cross/iframe03/b.html)

父页面 a.html 通过 hash 向子页面传值

var iframe = document.getElementById("iframe")

子页面监听 hash 改变,获取 hash 上的值:

// 
var hash_url = window.location.hash,
      datas = hash_url.split("#")[1].split("&"),
      data = {};
 
for(var i = 0;i<datas.length;i++){
    var t = datas[i].split("=");
    data[t[0]] = decodeURIComponent(t[1]);
}
document.domain = "jiaju.com";
switch(data["JJtype"])
    {
        case "height":
            try{top.window.document.getElementById(data["iframeID"]).height = data["height"];}catch(e){}
            break
        case "width":
            try{top.window.document.getElementById(data["iframeID"]).width = data["width"];}catch(e){}
            break
        case "callback":
            try{top.window[data["fn"]].call(document,data);}catch(e){}
            break
        default:
    }

【缺点】
1、传递数据量有限;
2、不太安全(明文);

window.name

【是什么?】
name 在浏览器环境中是一个全局window对象的属性
当在 iframe 中加载新页面时,name 的属性值依旧保持不变
name 属性仅对相同域名的 iframe 可访问

【优点】
数据量更大(2M)
更安全
可传递多种数据格式

【劣势】只适用于隐藏iframe的情形

【原理】
A 要把数据传递给 嵌套的页面 B,创建 B,把要传递的数据放入window.name。
打开Chrome的控制台,当前地址为:www.baidu.com。
你在console的控制台中输入window.name=‘moxiao’,然后将当前页面的地址栏的地址改为:mai.qq.com,然后在console的控制台中打印window.name将会显示:‘moxiao’。

调用方法

【目标】跨域 iframe 怎么调用 父页面方法。

同域时

【原理】

父页面内 iframe 加载完成后, $('#iframe')[0].contentWindow 指向 子iframe 的window;

页面:

  • window.self:当前窗口自身的引用;
  • window.parent:上一级父窗口的引用;
  • window.top:最顶层窗口的引用;

【示例】

父页面 调用 子iframe 方法

<body>
  <h2>父页面3</h2>

  <p>下面是 iframe 嵌入的 子页面</p>
  <iframe id="iframe" src="/html/iframe-child3.html" width="500" height="300"></iframe>

  <script src="/jquery/dist/jquery.min.js"></script>
  <script>
    function parentFun() {
      console.log('父 页面方法执行')
    }

    $('#iframe').on('load', function () {
      console.log(1, $('#iframe'))
      console.log(2, $('#iframe')[0])
      console.log(3, $('#iframe')[0].contentWindow)
      console.log(4, $('#iframe')[0].contentWindow.childFun)
      $('#iframe')[0].contentWindow.childFun()
    })
  </script>
</body>

子页面调用父页面方法

<body>
  <h2>子页面3</h2>

  <script>
    function childFun() {
      console.log('子 页面方法执行')
    }

    // 调用当前窗口自身
    // window.self.childFun()
    // childFun()

    // 上一级父窗口调引用
    window.parent.parentFun()

    // 最顶层窗口的引用
    window.top.parentFun() // 这里只嵌套了一层,也指向父窗口
  </script>
</body>

【注意 1】必须要在 子 iframe 加载完成,才能在父页面 调用 子iframe 的方法。

【注意 2】当页面中不存在 iframe 嵌套时,则 window.self, window.parent, window.top 三者均是当前窗口自身的引用。

不同域时

【问题】使用上面同源调用方式,会报错。
在这里插入图片描述
【解决】使用 HTML5 提供的一个跨域解决方案。(不跨域也能使用)

父页面向子页面通信 iframe.contentWindow.postMessage;
子页面向父页面通信 window.parent.postMessage 或 window.top.postMessage;
接收:直接 window 监听 onmessage 事件即可。

【示例】
1、父页面 (域名A) http://fangying.com/parent.html 定义函数 sayHi。
父页面 (域名B)嵌套子页面 http://fangyingui.online/child.html。

<iframe src="http://fangyingui.online/child.html"></iframe>

<script>
	function sayHi() {}
</script>

2、子页面 触发父页面 sayHi 方法;
子页面 发送数据

window.parent.postMessage({ isResetTheme: true },'*');

3、父页面监听 message 事件;

var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
	console.log(e.data)
})

父页面 监听子页面传递来的数据

【注意】postMessage 传值,无法传递 子iframe 的方法(会报错)。
(变通解决,在父页面定义同名的方法,用上面传递过来的参数,变相的解决)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值