以下代码有问题,导致Chrome和Firefox之间出现差异:

<button id="add">add element</button>
<div id="container"></div>
<script>
  const c = document.querySelector("#container");
  document.querySelector("#add").onclick = function() {
    const iframe = document.createElement("iframe");
    c.appendChild(iframe);

    const h1 = document.createElement("h1");
    h1.innerText = "hello";

    iframe.contentDocument.body.appendChild(h1);
  };
</script>


JSFiddle:https://jsfiddle.net/vtbcu1zj/

尝试在Chrome(应该可以正常运行)和Firefox(中断)中运行上述代码。

看来这是因为Firefox不认为iframe会立即加载,而Chrome却认为。进行以下更改可使代码在两种浏览器中均可工作:

iframe.onload = function () {
  iframe.contentDocument.body.appendChild(h1);
}

c.appendChild(iframe); // append after setting up event listener


这种差异的原因是什么?这是错误还是功能? Chrome是在这里做出错误的假设,还是Firefox处理不正确?

最佳答案

Chrome错误,per specs


  [...]如果元素未指定src属性,并且用户代理正在“首次”处理iframe的属性
  
  将任务排队以运行iframe load event steps
  此任务的任务源是DOM操作任务源。


因此,他们实际上应该等待当前事件循环结束,然后再调用负责生成iframe文档的这些iframe加载事件步骤。

在您调用iframe.contentDocument getter时,它应该已经返回null

但是确实,作为作者,您应该等待onload事件,该事件应始终异步触发。

09-20 23:27