现代浏览器具有一些新功能,使得这个任务比以前更容易。
PostMessage
postMessage API提供了一种简单的方法,用于在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){
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;
}
MutationObserver
在更现代的浏览器中,另一个进步是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。
如果您的代码溢出了页面主体,并且无法修复,那么使用document.documentElement的offsetHeight或scrollHeight属性是您的最佳选择。两者都有优缺点,最好测试一下,看哪个适合您。
其他问题
其他需要考虑的事项包括:页面上有多个iFrame,CSS :Checkbox和:Hover事件导致页面调整大小,避免在iFrames的body和html标签中使用height auto,以及窗口调整大小。
IFrame Resizer库
我已经将所有这些内容封装在一个简单的无依赖库中,还提供了一些额外的功能和页面大小检测算法,这里没有讨论。
https://github.com/davidjbradshaw/iframe-resizer
这在所有现代浏览器中都有效。
jsonp
来传输数据。 - charlietfl