最近在开发一个附件预览的页面,考虑到附件的安全性由后端对内容进行了加密,前端负责在页面引入iframe标签来加载数据,在这个过程中需要实时获取到iframe标签的渲染状态来判断什么时候loading结束:
这里我通过标签的方式来获取到iframe,再通过判断内部body是否有长度来确认loading状态,但是在页面中iframe加载到内容的情况下,无论怎么获取,js拿到的iframe内部都是空的
var iframe = document.getElementsByTagName('iframe')]
var loading = true
// 监听iframe加载完成
iframe.onload = function() {
// 获取iframe的document对象
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
// 获取iframe下的body元素
var iframeBody = iframeDoc.body;
loading = iframeBody.children?.length < 1
};
观察发现iframe的地址和项目的地址没有满足同源策略
同源策略限制:如果 iframe
加载的内容与主页面不在同一源(即协议、域名和端口相同),那么由于浏览器的同源策略,您将无法访问 iframe
的 contentDocument
。在这种情况下,即使 iframe
已经加载完成,您也无法读取其内容。
而对于跨域 iframe
,最可靠的方法是让 iframe
的内容主动通知主页面它已经渲染完成。这通常通过 postMessage
方法实现。如果您没有控制权限来修改 iframe
的内容,那么您将无法判断其渲染状态,因为浏览器的同源策略会阻止这种访问。
使用 postMessage
和 message
事件:
如果跨域 iframe
的内容允许,您可以使用 window.postMessage
方法来在 iframe
和主页面之间安全地传递消息。iframe
可以在其内容加载和渲染完成后向主页面发送一个消息,主页面可以通过监听 message
事件来接收这个消息。
// 在主页面中监听来自iframe的消息
window.addEventListener('message', function(event) {
if (event.origin !== '期望的iframe源的URL') return; // 安全检查
if (event.data === 'iframeRendered') {
console.log('iframe已经渲染完成');
}
}, false);
在 iframe
的内容中,当渲染完成时,您可以发送消息:
// 在iframe的内容中发送消息给主页面
window.parent.postMessage('iframeRendered', '*'); // 注意:'*' 表示接收方可以是任何源,出于安全考虑,应该替换为具体的源URL