现代浏览器具有一些新功能,使这项任务比以前更容易。
留言
The 发布消息 https://developer.mozilla.org/en-US/docs/Web/API/window.postMessageAPI 提供了一种在 iFrame 与其父级之间进行通信的简单方法。
要将消息发送到父页面,请按如下方式调用它。
parent.postMessage('Hello parent','http://origin-domain.com');
在另一个方向上,我们可以使用以下代码将消息发送到 iFrame。
var iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage('Hello my child', 'http://remote-domain.com:8080');
要接收消息,请为消息事件创建事件侦听器。
function receiveMessage(event)
{
if (event.origin !== "http://remote-domain.com:8080")
return;
console.log(event.data);
}
if ('addEventListener' in window){
window.addEventListener('message', receiveMessage, false);
} else if ('attachEvent' in window){ //IE
window.attachEvent('onmessage', receiveMessage);
这些示例使用 origin 属性来限制消息发送到的位置并检查消息的来源。可以指定*
允许发送到任何域,并且在某些情况下您可能希望接受来自任何域的邮件。但是,如果您这样做,您需要考虑安全隐患并对传入消息实施您自己的检查,以确保它包含您期望的内容。在这种情况下,iframe 可以将其高度设置为“*”,因为我们可能有多个父域。不过,最好检查传入消息是否来自 iFrame。
function isMessageFromIFrame(event,iframe){
var
origin = event.origin,
src = iframe.src;
if ((''+origin !== 'null') && (origin !== src.substr(0,origin.length))) {
throw new Error(
'Unexpect message received from: ' + origin +
' for ' + iframe.id + '. Message was: ' + event.data
);
}
return true;
}
变异观察者
现代浏览器的另一个进步是变异观察者 https://developer.mozilla.org/en/docs/Web/API/MutationObserver它允许你观察 DOM 的变化;因此现在可以检测可能影响 iFrame 大小的更改,而无需不断使用 setInterval 进行轮询。
function createMutationObserver(){
var
target = document.querySelector('body'),
config = {
attributes : true,
attributeOldValue : false,
characterData : true,
characterDataOldValue : false,
childList : true,
subtree : true
},
observer = new MutationObserver(function(mutations) {
parent.postMessage('[iframeResize]'+document.body.offsetHeight,'*');
});
log('Setup MutationObserver');
observer.observe(target, config);
}
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if (MutationObserver){
createMutationObserver();
}
计算出准确的高度
获取 iFrame 的准确高度并不像应有的那么简单,因为您可以选择六个不同的属性进行检查,但没有一个属性能够始终给出正确的答案。我想出的最佳解决方案是,只要您不使用 CSS 溢出 body 标记,此函数就可以工作。
function getIFrameHeight(){
function getComputedBodyStyle(prop) {
const style = document.defaultView.getComputedStyle(
document.body, null);
return parseInt(style.getPropertyValue(prop), 10);
}
return document.body.offsetHeight +
getComputedBodyStyle('marginTop') +
getComputedBodyStyle('marginBottom');
}
这是IE9版本,较长的IE8版本请看这里answer https://stackoverflow.com/questions/22402895/why-does-document-body-offsetheight-document-body-bottommargin-not-equal-docum.
如果您确实溢出了正文,并且无法修复代码来阻止这种情况,那么可以使用offsetHeight
or scrollHeight
的属性document.documentElement
是您最好的选择。两者都有优点和缺点,最好只是测试两者并看看哪种适合您。
其他事宜
其他需要考虑的事项包括:页面上有多个 iFrame、CSS :Checkbox 和 :Hover 事件导致页面调整大小、避免在 iFrame 的 body 和 html 标记中使用 height auto,最后调整窗口大小。
IFrame 调整器库
我已将所有这些内容封装在一个简单的无依赖库中,该库还提供了一些此处未讨论的额外函数和页面大小检测算法。
https://github.com/davidjbradshaw/iframe-resizer https://github.com/davidjbradshaw/iframe-resizer
这适用于所有现代浏览器。