我最近的项目是尝试使document.write异步,当然这几乎是不可能的任务,许多人都曾尝试过,但是我找不到任何好的解决方案,除了我自己想尝试的之外。 钩挂document.write非常简单:
var oldDocWrite = document.write;
document.write = function( content ) {
let domparser = new DOMParser().parseFromString(content, 'text/html'),
fragBody = document.createDocumentFragment(),
fragHead = document.createDocumentFragment(),
childNodesBody = DomParser.body.childNodes,
childNodesHead = DomParser.head.childNodes;
while (childNodesBody.length) {
//append nodes to the iframe
};
while (childNodesHead.length) {
//append nodes to the iframe
};
此代码的目标非常简单,我使用domparser api解析原始html,而不是创建2个文档片段,其中一个用于head标签,第二个用于body标签,而不是我要追加的内容通过appendChild将节点连接到某个iframe。 对于那些不熟悉这些api的人,请快速注意一下: 1.文档碎片在每个appendChild上都在减少,因此,当片段中的所有节点都附加到iframe时,这两个while循环都将停止。 2.DOMParser api将为任何脚本标签添加“不执行”(请参见规格),因此我实际上是在破坏每个脚本标签并创建一个新脚本标签。
因此,当html代码简单时,一切工作都很好,但是当html代码更复杂时,由于以下几个原因,我无法正确呈现html: 1.另一个iframe位于html内,我也需要在该iframe contentWindow中钩上document.write。 2.eventlisteners将无法正确触发。 3.另一个document.write调用(嵌套的),所以我需要停止在第一个/第二个/第三个/ ...后面追加第一个句柄并关闭递归操作(这非常困难,但我快到了) 您可以检查此非常有用的link:
长话短说,我最糟糕的问题是能够将原始html解析为节点并以正确的顺序附加节点,但一次也附加每个节点的能力,在我的示例中,如果某些节点具有比我实际更多的孩子附加节点及其所有子节点,那将无法正常工作,因为我需要将eventlistener添加到脚本标签,以便我可以在脚本标签完成执行后恢复附加,并且还可以钩住更多嵌套的iframe(如果存在),并且需要先附加iframe而不是钩它的contentWindow,所以我将需要分别追加每个节点,并且如果该节点具有子节点,则比分别追加每个子节点,并且如果该子节点还具有另一个子节点……
那么有什么好办法吗? DOMParser api由于存在许多问题(例如禁用js)而非常复杂,我想也许是通过正则表达式来实现的,但这似乎更为复杂。