关于javascript:document.write有哪些替代方案?

What are alternatives to document.write?

在教程中,我学会了使用document.write。 现在,我了解到很多人对此表示反对。 我已经尝试过print(),但是它确实将其发送到打印机。

那么我应该使用哪些替代方法,为什么不使用document.write? w3schools和MDN都使用document.write


替换HTML的原因是由于JavaScript函数document.write()邪恶。

它绝对是"错误的形式"。仅当您在页面加载时使用它时,它才适用于网页。如果在运行时使用它,它将用输入替换整个文档。而且,如果您将其应用为严格的XHTML结构,那么它甚至不是有效的代码。

问题:

document.write writes to the document stream. Calling document.write on a closed (or loaded) document automatically calls document.open which will clear the document.

-来自MDN的报价

document.write()有两个伙伴,document.open()document.close()。加载HTML文档时,该文档为"打开"状态。文档加载完成后,文档已"关闭"。此时使用document.write()将会删除整个(关闭的)HTML文档,并将其替换为新的(打开的)文档。这意味着您的网页已擦除自身,并开始从头开始编写新页面。

我相信document.write()也会导致浏览器的性能下降(如果我错了,请纠正我)。

一个例子:

此示例在页面加载后将输出写入HTML文档。当您按下" exterminate"按钮时,观看document.write()的邪恶力量会清除整个文档:

1
2
I am an ordinary HTML page.  I am innocent, and purely for informational purposes. Please do not <input type="button" onclick="document.write('This HTML page has been succesfully exterminated.')" value="exterminate"/>
me!

替代方案:

  • .innerHTML这是一个很好的选择,但是必须将此属性附加到要放置文本的元素上。

示例:document.getElementById('output1').innerHTML = 'Some text!';

  • .createTextNode()是W3C推荐的替代方法。

示例:var para = document.createElement('p');
para.appendChild(document.createTextNode('Hello, '));

注意:已知这会导致某些性能下降(比.innerHTML慢)。我建议改用.innerHTML

.innerHTML替代示例:

1
2
3
4
5
6
7
I am an ordinary HTML page.
I am innocent, and purely for informational purposes.
Please do not
<input type="button" onclick="document.getElementById('output1').innerHTML = 'There was an error exterminating this page. Please replace <wyn>.innerHTML</wyn> with <wyn>document.write()</wyn> to complete extermination.';" value="exterminate"/>
 me!
<p id="output1">
</p>


这是应该就地替换document.write的代码:

1
2
3
4
5
document.write=function(s){
    var scripts = document.getElementsByTagName('script');
    var lastScript = scripts[scripts.length-1];
    lastScript.insertAdjacentHTML("beforebegin", s);
}


只是在这里说一个注释,尽管由于性能方面的考虑(同步DOM注入和评估),人们对使用document.write非常不满意,但是如果使用document.write注入脚本标签,也没有实际的1:1替代方案。一经请求。

有很多很好的方法可以避免这样做(例如,像RequireJS这样的脚本加载器来管理您的依赖链),但是它们更具侵入性,因此最好在整个站点/应用程序中使用。


作为document.write的推荐替代方法,您可以使用DOM操作直接查询节点元素并将其添加到DOM。


问题取决于您实际要做什么。

通常,代替执行document.write,可以使用someElement.innerHTML或更好的document.createElementsomeElement.appendChild

您也可以考虑使用jQuery之类的库,并在其中使用修改功能:http://api.jquery.com/category/manipulation/


这可能是最正确,直接的替代方法:insertAdjacentHTML。


尝试使用getElementById()或getElementsByName()访问特定元素,然后使用innerHTML属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
    <body>
       
       
    </body>

    <script type="text/javascript">
        var myDiv1 = document.getElementById("myDiv1");
        var myDiv2 = document.getElementById("myDiv2");

        myDiv1.innerHTML ="Content of 1st DIV";
        myDiv2.innerHTML ="Content of second DIV element";
   
</html>


您可以结合使用insertAdjacentHTML方法和document.currentScript属性。

Element接口的insertAdjacentHTML()方法将指定的文本解析为HTML或XML,并将结果节点插入到DOM树中的指定位置:

  • 'beforebegin':在元素本身之前。
  • 'afterbegin':就在元素内部,在其第一个子元素之前。
  • 'beforeend':在元素的最后一个子元素之后。
  • 'afterend':在元素本身之后。

Document.currentScript属性返回当前正在处理其脚本的元素。最佳位置是在开始之前-新的HTML将在本身之前插入。

1
2
3
4
  document.currentScript.insertAdjacentHTML(
    'beforebegin',
    'this is the document.write alternative'
);


我看不到document.write的问题。如果您想在onload事件触发之前使用它(例如,大概是要从结构化数据中构建元素),则它是适合使用的工具。构建insertAdjacentHTML或将其显式添加到DOM后,没有性能优势。我只是用一个旧脚本对它进行了三种不同的测试,该脚本曾经用于安排4个调制解调器组中24/7服务的传入调制解调器呼叫。

到完成时,此脚本将创建3000多个DOM节点,主要是表单元。在运行Vista的Firefox上使用7年的旧PC上,使用本地12kb源文件中的document.write和三个可重复使用2000次的1px GIF,只需不到2秒的时间。该页面会弹出,显示完整的状态,可以处理事件。

使用insertAdjacentHTML不能直接替代,因为浏览器会关闭脚本需要保持打开状态的标记,并且最终花费两倍的时间才能最终创建变形的页面。将所有片段写入字符串,然后将其传递给insertAdjacentHTML会花费更长的时间,但是至少您可以按设计获得页面。其他选项(例如一次手动重新构建一个节点的DOM)是如此荒谬,以至于我什至不去。

有时document.write是要使用的东西。它是JavaScript中最古老的方法之一,这一事实并不是要反对它,而是要支持它-它是经过高度优化的代码,可以准确地实现其意图并自诞生以来就一直在这样做。

很高兴知道还有其他可供选择的后加载方法,但是必须理解,这些方法完全旨在用于不同的目的。即在创建DOM并为其分配内存后修改DOM。如果您的脚本旨在编写HTML的内容,那么使用这些方法在本质上会占用大量资源,而浏览器首先会从中创建HTML。

只需编写它,然后让浏览器和解释器完成工作即可。那就是他们的目的。

PS:我刚刚在body标记中使用onload参数进行了测试,即使在这一点上,文档仍然是opendocument.write()正常运行的功能。此外,最新版本的Firefox中的各种方法之间也没有明显的性能差异。当然,硬件/软件堆栈中的某处可能会进行大量缓存,但这确实是要点-让机器完成工作。不过,这可能会在廉价智能手机上有所作为。干杯!


我不确定这是否会正常工作,但我想到了

1
2
3
var docwrite = function(doc) {              
    document.write(doc);          
};

这为我解决了错误消息的问题。