【HTML】深入全掌握 iframe:了解 its 技术原理、优缺点、最佳应用场景及实战指南

前言:一、简单介绍及原理:1、iframe的主要特点:2、iframe的优点:3、iframe的缺点:4、解决方案:5、iframe的应用场景:

二、iframe的使用1、常用属性:2、使用(操作方法):1. iframe的简单使用2. 获取iframe元素3. 获取iframe元素值4. iframe获取父页面的信息

三、iframe的长轮询四、自适应 iframe - 广告嵌入1、去掉滚动条2、设置 iframe 的高为 body 的高

五、iframe 的安全性1、防嵌套网页2、 X-Frame-Options3、sandbox

六、iframe 的局限1、创建比一般的 DOM 元素慢了 1-2 个数量级2、阻塞页面加载3、唯一的连接池4、不利于 SEO

七、iframe 的实战指南总结

前言:

Web 应用开发中,包含其他网页的框架是很常见的需求。HTML 标签 iframe 提供了一个容器,可以用来嵌入其他页面,并且它自带了一些有用的特性,如调整大小、滚动等。

本文将深入介绍 iframe 技术原理、优缺点、最佳应用场景及实战指南,希望能帮助您更好地运用 iframe,提升 Web 应用开发效率。

一、简单介绍及原理:

这个代码会在当前页面中嵌入来自https://www.example.com的页面内容。

2. 获取iframe元素

要获取iframe元素,可以使用JavaScript中的document.getElementById()方法,传入iframe的id属性值作为参数。例如:

var iframe = document.getElementById('myFrame');

这个代码会获取一个指定id为“myFrame”的iframe元素。

3. 获取iframe元素值

要获取iframe元素中内容的值,可以使用JavaScript中的contentDocument属性。例如:

var iframe = document.getElementById('myFrame');

var iframeContent = iframe.contentDocument.body.innerHTML;

上述代码会获取一个指定id为“myFrame”的iframe元素的内部HTML内容。

4. iframe获取父页面的信息

在iframe中,可以使用window.parent属性来获取其所在的父窗口对象。通过这个对象,可以实现父子页面之间的相互通信。例如:

在父页面中:

function getTextFromIframe() {

var iframe = document.getElementById('myFrame');

var iframeContent = iframe.contentDocument.body.innerHTML;

iframe.contentWindow.postMessage({ message: 'getIframeContent' }, '*');

}

window.addEventListener('message', function(event) {

if (event.data.message === 'getIframeContent') {

var iframeContent = document.getElementById('myFrame').contentDocument.body.innerHTML;

event.source.postMessage({ message: 'iframeContent', content: iframeContent }, '*');

}

});

在iframe中:

window.addEventListener('message', function(event) {

if (event.data.message === 'getIframeContent') {

var iframeContent = document.getElementById('myFrame').contentDocument.body.innerHTML

event.source.postMessage({ message: 'iframeContent', content: iframeContent }, '*')

}

})

上述代码会获取一个指定id为“myFrame”的iframe元素的内部HTML内容,并通过window.postMessage()方法将内容发送给父窗口。在父窗口中,通过添加事件监听器,可以获取iframe传回的内容。

三、iframe的长轮询

长轮询 就是在ajax的 readyState = 4的时候,再次执行原函数 这里使用iframe也是一样的,异步创建iframe,然后 reload

var iframeCon = docuemnt.querySelector('#container'),

text; //传递的信息

var iframe = document.createElement('iframe'),

iframe.id = "frame",

iframe.style = "display:none;",

iframe.name = "polling",

iframe.src = "target.html";

iframeCon.appendChild(iframe);

iframe.onload = function () {

var iloc = iframe.contentWindow.location,

idoc = iframe.contentDocument;

setTimeout(function () {

text = idoc.getElementsByTagName('body')[0].textContent;

console.log(text);

iloc.reload(); // 刷新页面,再次获取信息,并且会触发 onload 函数

}, 2000);

}

这里使用 iframe 也是一样,异步创建 iframe,然后 reload。这样就可以实现 ajax 长轮询的效果。 当然,这里只是使用 reload 进行获取,也可以添加 iframe 和删除 iframe 的方式,进行发送信息,这些都是根据具体场景应用的。 另外在 iframe 中还可以实现异步加载 js 文件,不过,iframe 和主页是共享连接池的,现在基本上都被 XHR 和 hard callback 取缔了。

四、自适应 iframe - 广告嵌入

广告通常与原文无关,如果直接在某个 div 下嵌套,会造成 网页布局的紊乱,而且还需要引入额外的 css 和 js 文件,极大降低了网页的安全性。这些所有的弊端,都可以使用 iframe 进行解决。

可以将 iframe 理解为一个 沙盒,里面的内容能够被 top window 完全控制,而且,主页的 css 样式不会入侵 iframe 里面的样式

默认情况下,iframe 会自带滚动条,不会全屏,如果想自适应 iframe 的话:

1、去掉滚动条

2、设置 iframe 的高为 body 的高

var iwindow = iframe.contentWindow;

var idoc = iwindow.document;

iframe.height = idoc.body.offsetHeight;

五、iframe 的安全性

1、防嵌套网页

iframe 享有 click 优先权,当有人在伪造的主页中进行点击的话,如果点在 iframe 上,则会默认是在操作 iframe 的页面。所以,钓鱼网站就是使用这个技术,通过诱导用户进行点击。

为了防止网站被钓鱼,可以使用 window.top 来防止网页被 iframe,即限定你的网页不能被嵌套在任何网页内:

// iframe2.html

if (window != window.top) {

window.top.location.href = correctURL;

}

2、 X-Frame-Options

X-Frame-Options 是一个相应头,主要是描述服务器的网页资源的 iframe 权限,有3个选项:

DENY:当前页面不能被嵌套 iframe 里,即便是在相同域名的页面中嵌套也不允许,也不允许网页中有嵌套 iframeSAMEORIGIN:iframe 页面的地址只能为同源域名下的页面ALLOW-FROM:可以在指定的 origin url 的 iframe 中加载

简单示例:

X-Frame-Options: DENY

拒绝任何iframe的嵌套请求

X-Frame-Options: SAMEORIGIN

只允许同源请求,例如网页为 foo.com/123.php,則 foo.com 底下的所有网页可以嵌入此网页,但是 foo.com 以外的网页不能嵌入

X-Frame-Options: ALLOW-FROM http://s3131212.com

只允许指定网页的iframe请求,不过兼容性较差Chrome不支持

X-Frame-Options 其实就是将前端 js 对 iframe 的把控交给服务器来进行处理

// js

if (window != window.top) {

window.top.location.href = window.location.href;

}

// 等价于

X-Frame-Options: DENY

// js

if (top.location.hostname != window.location.hostname) {

top.location.href = window.location.href;

}

// 等价于

X-Frame-Options: SAMEORIGIN

该属性是对页面的 iframe 进行一个主要限制,不过,涉及 iframe 的 header 可不止这一个,另外还有一个 Content Security Policy,同样也可以对 iframe 进行限制

3、sandbox

sandbox 就是用来给指定 iframe 设置一个沙盒模型限制 iframe 的更多权限 sandbox 是 h5 的一个新属性,IE10+支持

启用方式就是使用 sandbox 属性:

这样会对 iframe 页面进行一系列的限制:

script 脚本不能执行不能发送 ajax 请求不能使用本地存储,即 localStorage,cookie 等不能创建新的弹窗和 window不能发送表单不能加载额外插件比如 flash 等

同时可以放宽一点权限。在 sandbox 里面进行一些简单设置:

常用的配置有:

配置效果allow-forms允许进行提交表单allow-scripts运行执行脚本allow-same-origin允许同域请求,比如 ajax,storageallow-top-navigation允许 iframe 能够主导 window.top 进行页面跳转allow-popups允许 iframe 中弹出新窗口,比如 window.open,target=“_blank”allow-pointer-lock在 iframe 中可以锁定鼠标,主要和鼠标锁定有关

可以通过在 sandbox 里,添加允许进行的权限.

这样可以保证 js 脚本的执行,但是禁止 iframe 里的 javascript 执行 top.location = self.location

六、iframe 的局限

1、创建比一般的 DOM 元素慢了 1-2 个数量级

iframe 的创建比其它包括 scripts 和 css 的 DOM 元素的创建慢了 1-2 个数量级,使用 iframe 的页面一般不会包含太多 iframe,所以创建 DOM 节点所花费的时间不会占很大的比重。但带来一些其它的问题:onload 事件以及连接池(connection pool)

2、阻塞页面加载

及时触发 window 的 onload 事件是非常重要的。onload 事件触发使浏览器的 “忙” 指示器停止,告诉用户当前网页已经加载完毕。当 onload 事件加载延迟后,它给用户的感觉就是这个网页非常慢。

window 的 onload 事件需要在所有 iframe 加载完毕后(包含里面的元素)才会触发。在 Safari 和 Chrome 里,通过 JavaScript 动态设置 iframe 的 SRC 可以避免这种阻塞情况

3、唯一的连接池

浏览器只能开少量的连接到 web 服务器。比较老的浏览器,包含 Internet Explorer 6 & 7 和 Firefox 2,只能对一个域名(hostname)同时打开2个连接。这个数量的限制在新版本的浏览器中有所提高。Safari 3+ 和 Opera 9+ 可同时对一个域名打开 4 个连接,Chrome 1+, IE 8 以及 Firefox 3 可以同时打开 6 个。

绝大部分浏览器,主页面和其中的 iframe 是共享这些连接的。这意味着 iframe 在加载资源时可能用光了所有的可用连接,从而阻塞了主页面资源的加载。如果 iframe 中的内容比主页面的内容更重要,这当然是很好的。但通常情况下,iframe 里的内容是没有主页面的内容重要的。这时 iframe 中用光了可用的连接就是不值得的了。一种解决办法是,在主页面上重要的元素加载完毕后,再动态设置 iframe 的 src。

4、不利于 SEO

搜索引擎的检索程序无法解读 iframe。

另外,iframe 本身不是动态语言,样式和脚本都需要额外导入。综上,iframe 应谨慎使用。

七、iframe 的实战指南

在实际开发中,我们常常需要用到 iframe 技术,下面列出了一些相关建议供您参考:

如果需要通过 iframe 加载同一站点内的内容,可以使用 Ajax 来替代。不建议使用 iframe 来让搜索引擎索引,因为嵌入的页面内容在外部不能被内容索引器抓取到。如果嵌入的页面属于第三方站点,需要注意身份验证等安全问题。对于一些特定的应用场景,如展示 Canvas、SVG 等动态效果或使用 WebGL 进行图形渲染,可以使用到 iframe。

总结