1

我正在尝试尽快添加一个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.bodyundefined在IE的时候处于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()
  }
}

我目前的提问方式......

  1. 问题是default这样吗?我应该在那里添加事件侦听器吗?我可以修改案例的顺序,以便事件侦听器是默认的?
  2. body有可能null参加DOMContentLoaded活动吗?
  3. 是否有可能还有其他价值document.readyState正在下降?
4

2 回答 2

1

我更新了逻辑,几乎可以消除错误,但我仍然看到document.bodynullwhen readyStateis interactive

一旦我评估了导致问题的特定浏览器场景,我将更新这篇文章。

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)
        )
      }
  }
}
于 2017-07-11T19:52:08.133 回答
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();
  }
}

接下来,您的事件处理程序注册错误。有 3 个参数,.addEventListener()第三个可以是两个值之一:

  1. 事件名称(字符串)
  2. 回调函数(引用或内联函数)

    3a。是否钩入捕获阶段(布尔值 -false默认情况下)

    3b。用于配置特征的选项对象(对象)

并且,addEventListener()它本身在将接收事件的对象上调用(window在这种情况下)。

它应该是:

    window.addEventListener('DOMContentLoaded', function(){
      this.appendIFrame.bind(this);
    });

另外(仅供参考),您确实应该手动插入语句结尾的分号,而不是依赖自动插入,因为在某些极端情况下会导致错误。

于 2017-06-29T21:57:55.830 回答