什么是 document.write 的替代品?

IT技术 javascript document.write
2021-01-17 16:56:18

在教程中,我学会了使用document.write. 现在我明白很多人不赞成这样做。我试过print(),但后来它确实将它发送到打印机。

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

6个回答

你的 HTML 被替换的原因是一个邪恶的 JavaScript 函数:document.write().

这绝对是“糟糕的形式”。如果您在页面加载时使用它,它仅适用于网页;如果您在运行时使用它,它将用输入替换您的整个文档。如果您将其应用为严格的 XHTML 结构,它甚至不是有效代码。


问题:

document.write写入文档流。调用document.write关闭(或加载)的文档会自动调用document.open将清除文档。

--引用自 MDN

document.write()有两个心腹,document.open(), 和document.close()加载 HTML 文档时,文档处于“打开状态”。 当文档完成加载时,文档已“关闭”。此时使用document.write()将删除您的整个(关闭的)HTML 文档并将其替换为一个新的(打开的)文档。这意味着您的网页已自行删除并开始编写新页面 - 从头开始​​。

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


一个例子:

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

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替代方案的示例

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 <code>.innerHTML</code> with <code>document.write()</code> to complete extermination.';" value="exterminate"/>
 me!
<p id="output1"></p>

那么邪恶是在文档关闭后才开始的?除了不流行之外,在此之前使用 document.write 有什么缺点吗?文档何时关闭是否存在任何实际不确定性
2021-03-23 16:56:18
@Pacerier 是的,但我的意思是document.write()在页面加载后使用速度较慢,因为它必须清除文档,然后在每次调用该函数时重新打开它。.innerHTML没有这样做,所以我很确定我读到它毕竟更快。我会寻找一个来源来支持它。我相信document.write()如果您在页面已经打开时使用它会很快。
2021-03-26 16:56:18
@Godisgood, document.write 不可能有性能问题,因为它与浏览器在加载初始 HTTP 响应时使用的功能完全相同。
2021-03-28 16:56:18
document.write()似乎仍然是cdn local fallback的最佳解决方案我还没有尝试过 getElementById/innerHTML,但是 createElement/insertBefore 解决方案结果证明是nonsynchronous 的
2021-04-07 16:56:18
@BobStein-VisiBone,是的,document.write()可以在页面加载期间调用,同时浏览器正在解析页面。一旦页面解析/加载完毕,调用此函数也将调用document.open(),它会擦除​​页面并从头开始。我想不出有任何理由在页面加载期间不使用该功能,除非与您在其他任何时候向页面添加内容的方式保持一致。一旦浏览器解析完文档,文档就会关闭。
2021-04-08 16:56:18

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

document.write=function(s){
    var scripts = document.getElementsByTagName('script');
    var lastScript = scripts[scripts.length-1];
    lastScript.insertAdjacentHTML("beforebegin", s);
}
如果页面上没有脚本,这将不起作用吗?
2021-03-17 16:56:18
@Noyo - 通常您在页面上的 <script> 内使用 document.write,例如 Github GIST:gist.github.com/adriank/7436248.js
2021-03-17 16:56:18
好吧,至少会在页面上(无论您将那个函数放在哪里),但是如果唯一的脚本位于 <head></head> 中怎么办?他提到的关键是insertAdjacentHTML 函数。
2021-03-24 16:56:18
奇怪,直到今天我才收到有人评论的电子邮件,哈哈。@Pons - 它应该是跨浏览器的,不过我不知道 IE。
2021-03-28 16:56:18
不错的小费。是跨浏览器吗?我已经在 Chrome 上对其进行了测试并且可以正常工作。
2021-04-09 16:56:18

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

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

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

document.currentScript属性返回<script>当前正在处理其脚本元素。最好的位置是beforebegin —— 新的 HTML 将被插入到<script>它自己之前为了匹配document.write的本机行为,可以文本定位在afterend,但是随后对函数的连续调用的节点不会按照您调用它们的顺序放置(就像document.write那样),而是相反。HTML 出现的顺序可能比它们相对于<script>标签的位置更重要,因此使用beforebegin

document.currentScript.insertAdjacentHTML(
  'beforebegin', 
  'This is a document.write alternative'
)

尽管这可能会回答问题,但请提供任何您能做的解释,以确保人们了解这里发生的事情。
2021-03-13 16:56:18
感谢这里的评论,我的问题得到了解决我已经解释了问题所在以及对我有用的内容:stackoverflow.com/a/64610187/7266835
2021-03-30 16:56:18

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

如果它解决了为什么document.write 有问题的问题,这将是一个更好的答案,就像这个答案一样
2021-04-04 16:56:18

只是在这里留下一个注释说,尽管document.write由于性能问题(同步 DOM 注入和评估)而强烈反对使用,但如果您使用按需注入脚本标签,没有实际的 1:1 替代方案document.write

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