当 DOM 元素从网络流入时,如何附加它们?

Tig*_*igt 6 html javascript streaming dom service-worker

我有一个元素想要作为请求的 HTML 流填充,而不是等待完整的响应。事实证明这非常困难。

\n\n

我尝试过的事情:

\n\n

1.milestoneNode.insertAdjacentHTML(\'beforebegin\', text)

\n\n

如果这有效的话,那就太好了。不幸的是,具有古怪解析的元素会破坏它 \xe2\x80\x94 例如<p><table>。由此产生的 DOM 可以被宽容地描述为 Dada。

\n\n

2.使用虚拟DOM/DOM更新管理库

\n\n

谷歌似乎incremental-dom最有前途,但它的patch()操作总是从容器节点的开头重新启动。不知道如何将其“冻结”到位。

\n\n

这也有至少在 JavaScript 中进行 HTML 标记化的负担,并且必须进行一些实际的树构建,除非提供格式良好的 XHTML5。(没有人这样做。)重新实现浏览器的HTML 解析器似乎是我犯了严重错误的标志。

\n\n

3.document.write()

\n\n

我很绝望。讽刺的是,这个古老的妖怪几乎具有我需要的行为,没有“扔掉现有页面”的事情。

\n\n

4. 附加到字符串,然后innerHTML定期对其进行 ing

\n\n

破坏了流式传输的意义,因为最终整个响应都会保存在内存中。还有重复序列化的开销。

\n\n

从好的方面来看,它确实有效。但肯定有更好的方法吗?

\n

Tig*_*igt 5

杰克·阿奇博尔德 (Jake Archibald) 发明了一个愚蠢的技巧,让浏览器能够实现这种行为。他的示例代码比我说的更好:

// Create an iframe:
const iframe = document.createElement('iframe');

// Put it in the document (but hidden):
iframe.style.display = 'none';
document.body.appendChild(iframe);

// Wait for the iframe to be ready:
iframe.onload = () => {
  // Ignore further load events:
  iframe.onload = null;

  // Write a dummy tag:
  iframe.contentDocument.write('<streaming-element>');

  // Get a reference to that element:
  const streamingElement = iframe.contentDocument.querySelector('streaming-element');

  // Pull it out of the iframe & into the parent document:
  document.body.appendChild(streamingElement);

  // Write some more content - this should be done async:
  iframe.contentDocument.write('<p>Hello!</p>');

  // Keep writing content like above, and then when we're done:
  iframe.contentDocument.write('</streaming-element>');
  iframe.contentDocument.close();
};

// Initialise the iframe
iframe.src = '';
Run Code Online (Sandbox Code Playgroud)

虽然<p>Hello!</p>是写入iframe,但是却出现在父文档中!这是因为解析器维护一个开放元素堆栈,新创建的元素将插入其中。我们搬家并不重要<streaming-element>,它只是有效。