我们从后端获取数据,需要将其写入iframe
。我们必须将iframe
高度设置为内容的高度。在内容实际为IN iframe
之前,我们无法获得正确的高度,这对于大量内容而言不是即时的。是否有回调知道写入何时完成?
现在,我们有一个计时器,但它是脆弱的代码:
//data received from backend
//write data to iframe
//$iframe is a jQuery DOM element
$iframe[0].contentDocument.open();
$iframe[0].contentDocument.write(data);
$iframe[0].contentDocument.close();
setTimeout(function (){
var scrollHeight = $iframe.contents().find('body')[0].scrollHeight
$iframe.css("height", scrollHeight );
}, 1000);
答案 0 :(得分:1)
您是否尝试过load
上的iframe
事件?
var doc = $iframe[0].contentDocument
doc.open()
doc.write(data)
doc.close()
$iframe.on('load', function () {
this.style.height = doc.body.scrollHeight + 'px'
})
答案 1 :(得分:0)
iframe确实有onload事件:
$iframe[0].contentDocument.open();
$iframe[0].contentDocument.write(data);
$iframe[0].contentDocument.close();
$iframe.onload = function() {
var scrollHeight = $iframe.contents().find('body')[0].scrollHeight
$iframe.css("height", scrollHeight);
};
答案 2 :(得分:0)
也许postMessage会帮助你。
var testData = 'test\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\n';
var $iframe = document.querySelector('#test-iframe');
var $button = document.querySelector('button');
// listen the callback message from iframe
window.self.addEventListener('message', function(ev) {
if (ev.data && ev.data.status === 'ready') {
$iframe.style.height = ev.data.height + 'px';
}
});
$button.addEventListener('click', function() {
// render content
$iframe.contentDocument.body.innerText = testData;
// send message to the top window
window.self.postMessage({
status: 'ready',
height: $iframe.contentDocument.body.scrollHeight
}, '*');
});
`
答案 3 :(得分:0)
您最好的选择是在iFrame中使用mutationObserver。这不像我害怕的回调那么简单。
以下是iFrame-resizer库用于解决此问题的代码。您需要更改调用sendSize
的行来调用您的回调方法。
function setupBodyMutationObserver(){
function addImageLoadListners(mutation) {
function addImageLoadListener(element){
if (false === element.complete) {
console.log('Attach listeners to ' + element.src);
element.addEventListener('load', imageLoaded, false);
element.addEventListener('error', imageError, false);
elements.push(element);
}
}
if (mutation.type === 'attributes' && mutation.attributeName === 'src'){
addImageLoadListener(mutation.target);
} else if (mutation.type === 'childList'){
Array.prototype.forEach.call(
mutation.target.querySelectorAll('img'),
addImageLoadListener
);
}
}
function removeFromArray(element){
elements.splice(elements.indexOf(element),1);
}
function removeImageLoadListener(element){
console.log('Remove listeners from ' + element.src);
element.removeEventListener('load', imageLoaded, false);
element.removeEventListener('error', imageError, false);
removeFromArray(element);
}
function imageEventTriggered(event,type,typeDesc){
removeImageLoadListener(event.target);
sendSize(type, typeDesc + ': ' + event.target.src, undefined, undefined);
}
function imageLoaded(event) {
imageEventTriggered(event,'imageLoad','Image loaded');
}
function imageError(event) {
imageEventTriggered(event,'imageLoadFailed','Image load failed');
}
function mutationObserved(mutations) {
sendSize('mutationObserver','mutationObserver: ' + mutations[0].target + ' ' + mutations[0].type);
//Deal with WebKit asyncing image loading when tags are injected into the page
mutations.forEach(addImageLoadListners);
}
function createMutationObserver(){
var
target = document.querySelector('body'),
config = {
attributes : true,
attributeOldValue : false,
characterData : true,
characterDataOldValue : false,
childList : true,
subtree : true
};
observer = new MutationObserver(mutationObserved);
console.log('Create body MutationObserver');
observer.observe(target, config);
return observer;
}
var
elements = [],
MutationObserver = window.MutationObserver || window.WebKitMutationObserver,
observer = createMutationObserver();
return {
disconnect: function (){
if ('disconnect' in observer){
console.log('Disconnect body MutationObserver');
observer.disconnect();
elements.forEach(removeImageLoadListener);
}
}
};
}