必威体育Betway必威体育官网
当前位置:首页 > IT技术

document中的write用法

时间:2019-06-17 17:43:10来源:IT技术作者:seo实验室小编阅读:88次「手机版」
 

document.write

一、document.write()运行原理

首先我们先了解一下这条语句运行的原理:

     document.write()是javascript中对document.open()所开启的文档流操作的API方法。

            它能够直接砸文档流中写入字符串,一旦文档流已经关闭,那么 document.write()就会重新运用document.open()打开新的文档流并写入,此时原来的文档流会被清空,已经渲染好的页面就会被覆盖,浏览器将重新构建DOM并渲染新的页面。

--(这也就是所谓的页面重写问题!!只发生在页面已经加载完,用它就清空以前的document)

二、写入文本(页面加载中可以写入,而不会出现重写页面问题)

下面来看看如何在利用 document.write()来写入文本。先考虑如下代码

<body>
<h1>Head</h1>
    <script>
        document.write('<p>hello document</p>');
    </script>
<h2>Tail</h2>
</body>

这是在h1h2之间内嵌一个脚本,使用document.write()来写入一个p标签。

刷新页面,可以看到最终的结果是

Head
hello document
Tail

即文本在脚本执行的位置被插入。这是因为,浏览器就解析HTML构建DOM的时候,如果遇到script就会暂停下来,解析script中的代码并执行,然后再继续解析剩余HTML。(阻塞进行的)

此时再去浏览器中检测DOM的结构,会发现scripth2之间多了一个p,浏览器在解析完h1之后,碰到script并执行之,此时document.write将一段HTML代码写入到文档流中,script执行完毕后,浏览器会解析文档流中的字符串,对新添加的p标签进行解析。

如果将渲染好的页面保存下来,不同的浏览器会有不同的结果。如Chrome和Firefox的做保存下来的页面文件中,script后面会增加p标签,而IE中则是维持原状。(这里指的是原有的HTML结构,不同浏览器将页面保存会作不同的处理,有些会增加一些不影响原有结构的标签或注释。这意味着,如果浏览器重新加载Chrome或Firefox中保存下来的页面文件,就会多出一个p标签。而IE浏览器则不会(可以自己动手试试!毕竟实践出真知)

三、写入脚本(注意加转义符号)

既然document.write可以写入p并被浏览器解析,那么自然地也可以写入script标签。

<script>
document.write('<script>alert("oops!!!")</script>');
</script>

我们将代码作出上面的改动,意图在利用document.write在页面中插入一段脚本。这段代码的本意是弹出一个窗口,阻塞浏览器对HTML的解析。

浏览器下刷新页面,发现并不管用,取而代之的是显示出一个没有意料到的页面。

Head


');

Tail

去检查DOM树,就会发现,这段脚本被拦腰截断了!浏览器将它解析成以下代码:

<script>

document.write('<script>alert("oops!!!")

</script>

');

插入文本中的</script>被当成了第一个script的闭合标签,因此这个段代码成了非法代码,因为document.write的调用书写不正确,缺少右边的括号)。此时,你可以在console中看到相关的错误信息。(控制台)

为了解决这个问题,我们可以对插入文本中闭合的的标签进行轻微修改,对最后一个</script>进行转义,变成<script>alert("oops!!!")<\ /script>或者<script>alert("oops!!!")</script\>都可;

此时再刷新一下页面,就可以看到预想中的结果。即页面中仅显示h1弹窗阻塞了浏览器对HTML的解析,关闭弹窗后,浏览器继续对HTML的解析并完成对页面的渲染。

再去看看DOM的结构,会发现在原有的script元素后面又多了一个新的<script>元素,其中所执行的代码就是我们的alert("opps!!!")

四、 异步引用外部JavaScript文件

 此时,必须注意:必须先运行document.open()清空文档,然后才能运行document.write()。

如果不先运行document.open(),直接运行document.write(),则会无效。chrome浏览器会有如下提示:

参数写在body内容的开头。如下文:

// test.js内容
document.open();
document.write('<p>test</p>');
document.close();


//html文件内容
<body>
  <script src='test.js' ansyc></script>
</body>

运行后的文件是:

<body>
  <p>test</p>
</body>

也就是会清空先前的页面,重新渲染,页面显示test字符串。

五、document.write使用的时机很重要

这样看来,利用document.write来在HTML中插入标签非常方便,就如同让浏览器在解析HTML的时候动态添加标签,而且只需要一行代码即可,不需要使用document.createElement再将其插入到DOM中。

但为什么大家都不建议使用document.write呢?这跟document.write的实现机制有关。在讨论之前,先看看下面的代码:

<body>
<h1>Head</h1>
    <script>
        settimeout(function(){
            document.write('<p>5 secs later</p>');
        }, 5000);
    </script>
<h2>Tail</h2>
</body>

对之前的代码作简单修改,这段代码同样是想插入一个p元素,但它是在5秒以后才执行。

刷新页面后,我们先看到了这样的显示效果:

Head

Tail

但是5秒以后,却变成了这样:(页面被重写了!!)

5 secs later

原来的h1h2甚至是scriptDOCTYPE还有head(当然,之前并没有往head添加任何标签,但如果添加了,这些标签也会有同样的下场),它们全部都不见了,取而代之的是一个基本的html结构,它是这样的:

<html>
<head></head>
<body>
<p>5 secs later</p>
</body>
</html>

这是一个全新的页面,document.write将之前的页面全部清除了,重新打开一页面并在这个页面上写入了新的标签。为什么会这样呢?(5s后页面加载完了,所以重写页面了!)

这是因为,5秒以后,浏览器早已完成了HTML的解析,并将文档流给关闭了。5秒后,timeout事件触发,document.write在执行的时候发现文档流已经关闭了,就会重新调用document.open打开一个新的文档流,而document.open的调用则会清除已有的文档。所以,最终看到的显示结果就是向上面那样,之前存在的页面都被清除掉了。

如果我们把document.write调用放到DOMcontentLoadedload的事件处理中,也会得到同样的结果。

这样看到,除非是在浏览器关闭文档之前调用document.write,否则当前页面都会被清除。

(说通俗点,如果能保证能在onload前执行,那么可以实现载入,而不是重写

六、应用场景

(1)加载需要配合JS脚本使用的外部CSS文件

利用下面的语句加载外部样式文件:

<script>
document.write('<link rel="stylesheet" href="style_neads_js.css">');
</script>

将所有需要用到JS的样式都放到这个外部样式表中,如果浏览器不禁用JS,那么该样式表就会被顺利加载,否则页面就不会使用该样式。(Don’t docwrite scripts)

(2)在新的窗口中写入新的页面数据时(新建一个页面就不会重写之前的)

既然在一个已加载完成的页面中调用document.write会重写整个页面,那么在一个新的窗口的空白页面中调用这个方法,就不存在这样的的问题了。

另外,在调用document.write,最好不要把document.opendocument.close漏掉,尽管多数时候浏览器会帮忙完成这些操作。即,一个标准的document.write应该是这样的:

document.open();
document.write('anthing')
document.close();

七、弊端

从某个角度说,document.write的实际功能确实很强,能够直接修改文档流,但它有很多弊端:

  • 在非loading阶段调用document.write会清除已加载的页面;
  • document.write不能够在XHTML中使用
  • 嵌入script中的document.write不能给任意节点添加子节点,因为它是随着DOM的构建执行的;
  • 利用document.write写入HTML字符串流并不是一个好方法,它有违DOM操作的概念;
  • 利用document.write添加script加载外部脚本时,浏览器的HTML解析会被script的加载所阻塞;

总结

综合上面所描述的关于document.write的种种特点,个人感觉还是不到迫不得已的时候,不要去使用document.write,使用不当document.write不仅会影响页面的性能,还容易造成各种bug。

要对DOM进行操作时,还是应当使用安全且对DOM的友好的API方法,以避免不必要的问题出现。

相关阅读

break 和continue 区别以及用法。

今天我们来介绍一下循环里的break 和continue的用法以及区别 想搞清楚break 和continue的用法以及区别必须要记住的两件两句话!

关于SetCapture() 和 ReleaseCapture()的用法

  查MSND,对SetCapture()函数的说明为:“该函数在属于当前线程的指定窗口里设置鼠标捕获。一旦窗口捕获了鼠标,所有鼠标输入都针对

Javascript:history.go()和history.back()的用法与区

Javascript:history.go()和history.back()的用法与区别简单的说就是:go(-1):返回上一页,原页面表单中的内容会丢失;back():返回上一页

matlab中contour 函数的用法(绘制等高线)

原文contour矩阵的等高线图全页折叠语法contour(Z)contour(Z,n)contour(Z,v)contour(X,Y,Z)contour(X,Y,Z,n)contour(X,Y,Z,v)con

document.all 在各浏览器中的支持不同

all 方法最初是由 IE 浏览器拥有的,并不属于 W3C 规范范畴,他返回调用 all 方法的 HTML 标记自身内的所有子孙元素的 HTML 标记集合

分享到:

栏目导航

推荐阅读

热门阅读