我正在尝试尽快将iframe
元素附加到document.body
。
错误报告涉及所有4种主要浏览器(Chrome,Safari,FF,IE - 各种版本),我们看到document.body
为null
。我认为当我的JS文件被缓存并快速加载时会发生这种情况。
以下是插入iframe
:
private loadIFrame(): void {
switch (document.readyState) {
case 'uninitialized':
case 'loading':
case 'loaded':
window.addEventListener('DOMContentLoaded',
this.appendIFrame.bind(this)
)
break
case 'interactive':
case 'complete':
default:
this.appendIFrame()
}
}
private appendIFrame(): void {
if (document.getElementById('iframeId')) {
return
}
let iFrame: HTMLIFrameElement = document.createElement('iframe')
iFrame.src = document.location.protocol + this.ORIGIN + '/iframe.html'
iFrame.id = 'iframeId'
// document.body is null here
document.body.appendChild(iFrame)
}
我很难在干净的环境中重现这个问题,这让我猜测这是如何在野外发生的。
我最初尝试使用此rreadyState
逻辑,但在document.body
状态下,我们在IE中看到undefined
为loading
。
private loadIFrame(): void {
switch (document.readyState) {
case 'uninitialized':
case 'loading':
window.addEventListener('DOMContentLoaded',
this.appendIFrame.bind(this)
)
break
case 'loaded':
case 'interactive':
case 'complete':
default:
this.appendIFrame()
}
}
我目前的质疑......
default
案例吗?我应该在那里添加事件监听器吗?我可以修改案例的顺序,以便事件监听器是默认的吗?body
事件可能null
是DOMContentLoaded
吗?document.readyState
的其他值正在落空?答案 0 :(得分:1)
首先,如果您已经检查了readyState
并确定它是loaded
,那么为什么要设置一个已经过去的事件处理程序(DOMContentLoaded
)?
你可以这样做:
private loadIFrame(): void {
switch (document.readyState) {
case 'uninitialized':
case 'loading':
case 'loaded':
this.appendIFrame.bind(this);
break;
case 'interactive':
case 'complete':
default:
this.appendIFrame();
}
}
接下来,您的事件处理程序注册是错误的。 .addEventListener()
有3个参数,第三个参数可以是两个值中的一个:
回调函数(引用或内联函数)
3A。是否挂钩到捕获阶段(默认为布尔 - false
)
3B。用于配置特征(对象)的选项对象
并且,addEventListener()
本身会在将接收事件的对象上调用(在本例中为window
)。
应该是:
window.addEventListener('DOMContentLoaded', function(){
this.appendIFrame.bind(this);
});
另外(FYI),你真的应该手动插入你的语句结束分号而不是依赖于自动插入,因为存在导致错误的边缘情况。
答案 1 :(得分:0)
我更新了逻辑,我能够几乎消除错误,但当document.body
为{{null
时,我仍然看到readyState
为interactive
1}}。
一旦我评估导致问题的特定浏览器方案,我就会更新此帖子。
private loadIFrame(): void {
switch (document.readyState) {
case 'uninitialized':
case 'loading':
case 'loaded':
document.addEventListener('DOMContentLoaded',
this.appendIFrame.bind(this)
)
break
case 'interactive':
case 'complete':
default:
if(document.body) {
this.appendIFrame()
} else {
window.addEventListener('load',
this.appendIFrame.bind(this)
)
}
}
}