关于document.write
document.write的用处
document.write
是JavaScript中对document.open
所开启的文档流(document stream操作的API方法,它能够直接在文档流中写入字符串,一旦文档流已经关闭,那document.write
就会重新利用document.open
打开新的文档流并写入,此时原来的文档流会被清空,已渲染好的页面就会被清除,浏览器将重新构建DOM并渲染新的页面。
写入文本
下面来看看如何在利用document.write
来写入脚本。先考虑如下代码:
<!DOCTYPE HTML>
<html>
<head>
</head>
<body><h1>Head</h1><script>document.write('<p>hello document</p>');</script><h2>Tail</h2>
</body>
</html>
这段在h1
和h2
之间内嵌一个脚本,使用document.write
来写入一个p
标签。
刷新页面,可以看到最终的结果是
Headhello documentTail
即要文本在脚本执行的位置被插入。这是因为,浏览器就解析HTML构建DOM的时候,如果遇到script
就会暂停下来,解析script
中的代码并执行,然后再继续解析剩余HTML。
此时再去浏览器中检测DOM的结构,会发现script
与h2
之间多了一个p
,浏览器在解析完h1
之后,碰到script
并执行之,此时document.write
将一段HTML代码写入到文档流中,script执行完毕后,浏览器会解析文档流中的字符串,对新添加的p
标签进行解析。
如果将渲染好的页面保存下来,不同的浏览器会有不同的结果。如Chrome和Firefox的做保存下来的页面文件中,script
后面会增加p
标签,而IE中则是维持原状。(这里指的是原有的HTML结构,不同浏览器将页面保存会作不同的处理,有些会增加一些不影响原有结构的标签或注释。这意味着,如果浏览器重新加载Chrome或Firefox中保存下来的页面文件,就会多出一个p
标签。
写入脚本
既然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中看到相关的错误信息。
为了解决这个问题,我们可以对插入文本中闭合的的标签进行轻微修改,对最后一个>
进行转义,变成\>
。
此时再刷新一下页面,就可以看到预想中的结果。即页面中仅显示h1
,弹窗阻塞了浏览器对HTML的解析,关闭弹窗后,浏览器继续对HTML的解析并完成对页面的渲染。
再去看看DOM的结构,会发现在原有的script
元素后面又多了一个新的<script>
元素,其中所执行的代码就是我们的alert("opps!!!")
。
document.write使用的时机很重要
这样看来,利用document.write
来在HTML中插入标签非常方便,就如同让浏览器在解析HTML的时候动态得添加标签,而且只需要一行代码即可,不需要使用document.createElement
再将其插入到DOM中。
但为什么大家都不建议使用document.write呢?这跟document.write
的实现机制有关。在讨论之前,先看看下面的代码:
<script>setTimeout(function(){document.write('<p>5 secs later</p>');}, 5000);
</script>
对之前的代码作简单修改,这段代码同样是想插入一个p
元素,但它是在5秒以后才执行。
刷新页面后,我们看到了这样的显示效果:
HeadTail
但是5秒以后,页面却变成了这样:
5 secs later
原来的h1
、h2
甚至是script
,DOCTYPE
还有head
(当然,之前并没有往head添加任何标签,但如果添加了,这些标签也会有同样的下场),它们全部都不见了,取而代之的是一个基本的html结构,它是这样的:
<html><head></head><body><p>5 secs later</p></body>
</html>
这是一个全新的页面,document.write
将之前的页面全部清除了,重新打开一页面并在这个页面上写入了新的标签。为什么会这样呢?
回到再文章开头所描述文字,就会找到结果。这是因为,5秒以后,浏览器早已完成了HTML的解析,并将文档流给关闭了。5秒后,timeout
事件触发,document.write
在执行的时候发现文档流已经关闭了,就会重新调用document.open
打开一个新的文档流,而document.open
的调用则会清除已有的文档。所以,最终看到的显示结果就是向上面那样,之前存在的页面都被清除掉了。
如果我们把document.write
调用放到DOMCOntentLoaded
或load
的事件处理中,也会得到同样的结果。
这样看到,除非是在浏览器关闭文档之前调用document.write
,否则当前页面都会被清除。
这一个特性决定了document.write
在实际开发中的应用范围和时机。那么,什么时候应该使用document.write
呢?
在网上搜集的资料看,一般在下列情景下可以利用document.write
来完成某些特殊的操作:
加载需要配合JS脚本使用的外部CSS文件
利用下面的语句加载外部样式文件:
<scirpt>document.write('<link rel="stylesheet" href="style_neads_js.css">');
</script>
将所有需要用到JS的样式都放到这个外部样式表中,如果浏览器不禁用JS,那么该样式表就会被顺利加载,否则页面就不会使用该样式。(Don’t docwrite scripts)
在新的窗口中写入新的页面数据时
既然在一个已加载完成的页面中调用document.write
会重写整个页面,那么在一个新的窗口的空白页面中调用这个方法,就不存在这样的的问题了。
另外,在调用document.write
,最好不要把document.open
和document.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方法,以避免不必要的问题出现。
上述信息都是以自己做的小测试和网上的参考资料为基础总结出来,有错误的地方,欢迎大家指出,我会尽快作出修正。
参考
js中document.write的那点事
document.wrtie_MDN
Three JavaScript articles and one best practice
Don’t docwrite scripts
Why is document.write considered a “bad practice”?
转载于:https://www.cnblogs.com/elcarim5efil/p/4749262.html
关于document.write相关推荐
- Technology Document Guide of TensorRT
Technology Document Guide of TensorRT Abstract 本示例支持指南概述了GitHub和产品包中包含的所有受支持的TensorRT 7.2.1示例.Tensor ...
- js动态创建元素之一--document.write
以我曾经写过的例子举例 如上图,乡镇街道的名字和数目是根据数据库的数据获取的,有几个乡镇,就会显示出来几个,这就要求动态获取乡镇名称和数目,以下代码中用到了document.write创建动态页面,在 ...
- $(function(){})、$(document).ready(function(){})....../ ready和onload的区别
1.window.onload 当一个文档完全下载到浏览器中时,会触发 window.onload 事件. 这意味着页面上的全部元素对 javascript 而言都是可以访问的,这种情况对编写功能性的 ...
- document.getElementById与document.getElementsById的区别
document.getElementById 是用Id选择元素,一个Id只对应一个元素. document.getElementsById 是用元素名称选择元素一个元素名称可能有很多元素,取的是集, ...
- 【加强版】js原生实现拖拽效果,这次没有用document的mousedown、mousemove、mouseup事件我们来点实际的(但是有个弊端:拖拽过程中鼠标会变成一个禁用符号,不太友好)
<div class='dragged'></div> //初始化需要拖拽的列initDrags() {var arr = document.querySelectorAll( ...
- JS document
<!DOCTYPE html> <html><head><meta charset="UTF-8"><title>< ...
- js里的document对象大全(DOM操作)
什么是DOM document object model 的简称,意思为文档对象模型.主要用来对文档中的html节点进行操作. Dom的操作简单示例: <div id="t1" ...
- JavaScript Document
document:文档对象 document.getElementById();//根据ID获取元素对象 document.getElementsByTagName();//根据标签名获取元素对象数组 ...
- document.all与WEB标准
1.DOM WEB标准现在可真是热门中热门,不过下面讨论的是一个不符合标准的document.all[].DOM--DOCUMENT OBJECT MODEL文档对象模型,提供了访问文档对象的方法.例 ...
- DOM---文档对象模型(Document Object Model)的基本使用
一.DOM简介 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言的标准编程接口.它是一种与平台和语言无关的应用程序接口(API),它可以动态 ...
最新文章
- 一步步玩pcDuino3--mmc下的裸机流水灯
- 卷积层计算量(FLOPS)和参数量的计算
- R语言成功加载rJava方法
- ios找不到信任证书_ios信任苹果企业级应用
- openwrt系统安装到云服务器异常,OpenWrt路由器系统下服务OpenClash 安装教程及其折腾踩坑记录...
- 第一节《Git初始化》
- 贪心算法(Greedy Algorithm)
- numeric转换varchar_将数据类型varchar转换为numeric时选择失败
- python使用opencv保存视频_Pythone OpenCV学习笔记之:视频文件读取与保存
- c#中类的简单使用学习
- 【bzoj1050】[HAOI2006]旅行comf 并查集
- window操作大全
- 技能梳理27@体感机械臂
- Tableau数据可视化案例
- html信纸效果,纯css3实现信纸/同学录效果(代码示例)
- 校招行测笔试-言语理解与表达
- 从0基础到10w册数据分析书籍的畅销书作家
- 2021-05-14 kk日记,TBASE数据表更换shard key
- R的可视化以及ggplot2
- java poi打印excel_POI打印Excel报表
热门文章
- BlockChain- 以太坊架构
- python编程环境要求_python公开课|我们需要优秀Python编程环境的要求居然是这些...
- python词云代码简单_Python 简单实现标签词云
- jsr223 java_Jmeter 组件 JSR223 使用详解
- CVPR 2017 CA:《Context-Aware Correlation Filter Tracking》论文笔记
- 2017年10月18日普及组 文件名排序
- python爬虫与数据分析实战27_Python网络爬虫与文本数据分析
- 网页 两秒弹出窗口_电脑网页打不开但qq能用怎么回事
- 20210614 So-called的用法
- 无障碍开发(三)之ARIA aria-***属性值