document.write 的替代品是什么?

发布于 2024-10-09 22:05:30 字数 212 浏览 1 评论 0原文

在教程中我学会了使用 document.write。现在我明白许多人对此不以为然。我尝试过 print(),但随后它实际上将其发送到打印机。

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

In tutorials I've learnt to use document.write. Now I understand that by many this is frowned upon. I've tried print(), but then it literally sends it to the printer.

So what are alternatives I should use, and why shouldn't I use document.write? Both w3schools and MDN use document.write.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

苏别ゝ 2024-10-16 22:05:30

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

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


问题:

document.write 写入文档流。调用 document.write在关闭(或加载)文档上自动调用 document.打开,这将清除文档。

-- 引自 MDN

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

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


示例:

此示例将输出写入页面之后的 HTML 文档已加载。观看 document.write() 的邪恶力量会清除整个文档:

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>

The reason that your HTML is replaced is because of an evil JavaScript function: document.write().

It is most definitely "bad form." It only works with webpages if you use it on the page load; and if you use it during runtime, it will replace your entire document with the input. And if you're applying it as strict XHTML structure it's not even valid code.


the problem:

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.

-- quote from the MDN

document.write() has two henchmen, document.open(), and document.close(). When the HTML document is loading, the document is "open". When the document has finished loading, the document has "closed". Using document.write() at this point will erase your entire (closed) HTML document and replace it with a new (open) document. This means your webpage has erased itself and started writing a new page - from scratch.

I believe document.write() causes the browser to have a performance decrease as well (correct me if I am wrong).


an example:

This example writes output to the HTML document after the page has loaded. Watch document.write()'s evil powers clear the entire document when you press the "exterminate" button:

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!


the alternatives:

  • .innerHTML This is a wonderful alternative, but this attribute has to be attached to the element where you want to put the text.

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

  • .createTextNode() is the alternative recommended by the W3C.

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

NOTE: This is known to have some performance decreases (slower than .innerHTML). I recommend using .innerHTML instead.


the example with the .innerHTML alternative:

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>

熟人话多 2024-10-16 22:05:30

以下是应就地替换 document.write 的代码:

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

Here is code that should replace document.write in-place:

document.write=function(s){
    var scripts = document.getElementsByTagName('script');
    var lastScript = scripts[scripts.length-1];
    lastScript.insertAdjacentHTML("beforebegin", s);
}
傾旎 2024-10-16 22:05:30

您可以将 insertAdjacentHTML 方法与 document.currentScript 属性。

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

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

document.currentScript 属性返回当前正在处理其脚本的

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

You can combine insertAdjacentHTML method and document.currentScript property.

The insertAdjacentHTML() method of the Element interface parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position:

  • 'beforebegin': Before the element itself.
  • 'afterbegin': Just inside the element, before its first child.
  • 'beforeend': Just inside the element, after its last child.
  • 'afterend': After the element itself.

The document.currentScript property returns the <script> element whose script is currently being processed. Best position will be beforebegin — new HTML will be inserted before <script> itself. To match document.write's native behavior, one would position the text afterend, but then the nodes from consecutive calls to the function aren't placed in the same order as you called them (like document.write does), but in reverse. The order in which your HTML appears is probably more important than where they're place relative to the <script> tag, hence the use of beforebegin.

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

话少情深 2024-10-16 22:05:30

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

As a recommended alternative to document.write you could use DOM manipulation to directly query and add node elements to the DOM.

神爱温柔 2024-10-16 22:05:30

只是在这里留言说一下,尽管由于 性能问题(同步 DOM 注入和评估),如果您使用 ,也没有实际的 1:1 替代方案 document.write 根据需要注入脚本标签。

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

Just dropping a note here to say that, although using document.write is highly frowned upon due to performance concerns (synchronous DOM injection and evaluation), there is also no actual 1:1 alternative if you are using document.write to inject script tags on demand.

There are a lot of great ways to avoid having to do this (e.g. script loaders like RequireJS that manage your dependency chains) but they are more invasive and so are best used throughout the site/application.

ˉ厌 2024-10-16 22:05:30

我没有看到 document.write 的问题。如果您在 onload 事件触发之前使用它(您可能会这样做),例如从结构化数据构建元素,那么它是合适的工具。使用 insertAdjacentHTML 或在构建 DOM 后显式向 DOM 添加节点并没有性能优势。我只是用一个旧脚本以三种不同的方式测试了它,我曾经用它来安排一组 4 个调制解调器上的 24/7 服务的传入调制解调器呼叫。

完成时,该脚本创建了 3000 多个 DOM 节点,其中大部分是表格单元格。在运行 Vista 上的 Firefox 的 7 年旧 PC 上,使用本地 12kb 源文件和三个 1px GIF(重复使用约 2000 次)中的 document.write 进行这个小练习只需不到 2 秒。该页面会弹出并完全成形,准备好处理事件。

使用 insertAdjacentHTML 并不能直接替代,因为浏览器会关闭脚本要求保持打开状态的标签,并且需要两倍的时间来最终创建一个损坏的页面。将所有部分写入字符串,然后将其传递给 insertAdjacentHTML 需要更长的时间,但至少您得到了设计的页面。其他选项(比如一次手动重建 DOM 一个节点)太荒谬了,我什至不会去那里。

有时 document.write 是可以使用的。它是 JavaScript 中最古老的方法之一,这一事实并不是反对它,而是支持它——它是高度优化的代码,完全符合它的预期,并且自诞生以来一直在做。

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

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

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

I fail to see the problem with document.write. If you are using it before the onload event fires, as you presumably are, to build elements from structured data for instance, it is the appropriate tool to use. There is no performance advantage to using insertAdjacentHTML or explicitly adding nodes to the DOM after it has been built. I just tested it three different ways with an old script I once used to schedule incoming modem calls for a 24/7 service on a bank of 4 modems.

By the time it is finished this script creates over 3000 DOM nodes, mostly table cells. On a 7 year old PC running Firefox on Vista, this little exercise takes less than 2 seconds using document.write from a local 12kb source file and three 1px GIFs which are re-used about 2000 times. The page just pops into existence fully formed, ready to handle events.

Using insertAdjacentHTML is not a direct substitute as the browser closes tags which the script requires remain open, and takes twice as long to ultimately create a mangled page. Writing all the pieces to a string and then passing it to insertAdjacentHTML takes even longer, but at least you get the page as designed. Other options (like manually re-building the DOM one node at a time) are so ridiculous that I'm not even going there.

Sometimes document.write is the thing to use. The fact that it is one of the oldest methods in JavaScript is not a point against it, but a point in its favor - it is highly optimized code which does exactly what it was intended to do and has been doing since its inception.

It's nice to know that there are alternative post-load methods available, but it must be understood that these are intended for a different purpose entirely; namely modifying the DOM after it has been created and memory allocated to it. It is inherently more resource-intensive to use these methods if your script is intended to write the HTML from which the browser creates the DOM in the first place.

Just write it and let the browser and interpreter do the work. That's what they are there for.

PS: I just tested using an onload param in the body tag and even at this point the document is still open and document.write() functions as intended. Also, there is no perceivable performance difference between the various methods in the latest version of Firefox. Of course there is a ton of caching probably going on somewhere in the hardware/software stack, but that's the point really - let the machine do the work. It may make a difference on a cheap smartphone though. Cheers!

忆沫 2024-10-16 22:05:30

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

通常,您可以使用 someElement.innerHTML 或更好的 document.createElementsomeElement.appendChild< 来代替 document.write /代码>。

您还可以考虑使用像 jQuery 这样的库并使用其中的修改函数: http://api.jquery .com/category/manipulation/

The question depends on what you are actually trying to do.

Usually, instead of doing document.write you can use someElement.innerHTML or better, document.createElement with an someElement.appendChild.

You can also consider using a library like jQuery and using the modification functions in there: http://api.jquery.com/category/manipulation/

吾家有女初长成 2024-10-16 22:05:30

这可能是最正确、最直接的替换:insertAdjacentHTML

This is probably the most correct, direct replacement: insertAdjacentHTML.

甜味拾荒者 2024-10-16 22:05:30

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

<html>
    <body>
        <div id="myDiv1"></div>
        <div id="myDiv2"></div>
    </body>

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

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

Try to use getElementById() or getElementsByName() to access a specific element and then to use innerHTML property:

<html>
    <body>
        <div id="myDiv1"></div>
        <div id="myDiv2"></div>
    </body>

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

        myDiv1.innerHTML = "<b>Content of 1st DIV</b>";
        myDiv2.innerHTML = "<i>Content of second DIV element</i>";
    </script>
</html>
囚你心 2024-10-16 22:05:30

您可能会发现此方法很有帮助。它是一个普通的 JS,它接受输入上的字符串或节点。刚刚编写此内容是为了支持 Adob​​e Target 跟踪。

function documentWrite(newNode) {
  // convert string to a fragment
  if (typeof newNode === 'string') {
    newNode = document.createRange().createContextualFragment(newNode);
  }
  var body = document.querySelector('body')
  if (body) {
    body.appendChild(newNode)
  }
}

You may find this method helpful. It's a vanilla JS and it accepts either string or node on the input. Just wrote this to support Adobe Target tracking.

function documentWrite(newNode) {
  // convert string to a fragment
  if (typeof newNode === 'string') {
    newNode = document.createRange().createContextualFragment(newNode);
  }
  var body = document.querySelector('body')
  if (body) {
    body.appendChild(newNode)
  }
}
记忆で 2024-10-16 22:05:30

使用和调用该函数,如下所示

var  documentwrite =(value, method="", display="")=>{
            switch(display) {
                case "block":
                 var x = document.createElement("p");
                  break;
                  case "inline":
                 var x = document.createElement("span");
                  break;
                default:
                 var x = document.createElement("p");
              }
            
            var t = document.createTextNode(value);
            x.appendChild(t);
            
            if(method==""){
             document.body.appendChild(x);
            }
            else{
            document.querySelector(method).appendChild(x);
           
            }
        }

根据您的要求

  documentwrite("My sample text"); //print value inside body
  documentwrite("My sample text inside id", "#demoid", "block");  // print value inside id and display block
  documentwrite("My sample text inside class", ".democlass","inline"); // print value inside class and and display inline 

Use

var  documentwrite =(value, method="", display="")=>{
            switch(display) {
                case "block":
                 var x = document.createElement("p");
                  break;
                  case "inline":
                 var x = document.createElement("span");
                  break;
                default:
                 var x = document.createElement("p");
              }
            
            var t = document.createTextNode(value);
            x.appendChild(t);
            
            if(method==""){
             document.body.appendChild(x);
            }
            else{
            document.querySelector(method).appendChild(x);
           
            }
        }

and call the function based on your requirement as below

  documentwrite("My sample text"); //print value inside body
  documentwrite("My sample text inside id", "#demoid", "block");  // print value inside id and display block
  documentwrite("My sample text inside class", ".democlass","inline"); // print value inside class and and display inline 
佼人 2024-10-16 22:05:30

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

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

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

I'm not sure if this will work exactly, but I thought of

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

This solved the problem with the error messages for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文