关于document.write
document.write的用處
document.write是JavaScript中對(duì)document.open所開啟的文檔流(document stream操作的API方法,它能夠直接在文檔流中寫入字符串,一旦文檔流已經(jīng)關(guān)閉,那document.write就會(huì)重新利用document.open打開新的文檔流并寫入,此時(shí)原來的文檔流會(huì)被清空,已渲染好的頁面就會(huì)被清除,瀏覽器將重新構(gòu)建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之間內(nèi)嵌一個(gè)腳本,使用document.write來寫入一個(gè)p標(biāo)簽。
刷新頁面,可以看到最終的結(jié)果是
Headhello documentTail即要文本在腳本執(zhí)行的位置被插入。這是因?yàn)?#xff0c;瀏覽器就解析HTML構(gòu)建DOM的時(shí)候,如果遇到script就會(huì)暫停下來,解析script中的代碼并執(zhí)行,然后再繼續(xù)解析剩余HTML。
此時(shí)再去瀏覽器中檢測(cè)DOM的結(jié)構(gòu),會(huì)發(fā)現(xiàn)script與h2之間多了一個(gè)p,瀏覽器在解析完h1之后,碰到script并執(zhí)行之,此時(shí)document.write將一段HTML代碼寫入到文檔流中,script執(zhí)行完畢后,瀏覽器會(huì)解析文檔流中的字符串,對(duì)新添加的p標(biāo)簽進(jìn)行解析。
如果將渲染好的頁面保存下來,不同的瀏覽器會(huì)有不同的結(jié)果。如Chrome和Firefox的做保存下來的頁面文件中,script后面會(huì)增加p標(biāo)簽,而IE中則是維持原狀。(這里指的是原有的HTML結(jié)構(gòu),不同瀏覽器將頁面保存會(huì)作不同的處理,有些會(huì)增加一些不影響原有結(jié)構(gòu)的標(biāo)簽或注釋。這意味著,如果瀏覽器重新加載Chrome或Firefox中保存下來的頁面文件,就會(huì)多出一個(gè)p標(biāo)簽。
寫入腳本
既然document.write可以寫入p并被瀏覽器解析,那么自然地也可以寫入script標(biāo)簽。
<script>document.write('<script>alert("oops!!!")</script>'); </script>我們將代碼作出上面的改動(dòng),意圖在利用document.write在頁面中插入一段腳本。這段代碼的本意是彈出一個(gè)窗口,阻塞瀏覽器對(duì)HTML的解析。
瀏覽器下刷新頁面,發(fā)現(xiàn)并不管用,取而代之的是顯示出一個(gè)沒有意料到的頁面。
Head'); Tail去檢查DOM樹,就會(huì)發(fā)現(xiàn),這段腳本被攔腰截?cái)嗔?#xff01;瀏覽器將它解析成以下代碼:
<script>document.write('<script>alert("oops!!!") </script> ');插入文本中的</script>被當(dāng)成了第一個(gè)script的閉合標(biāo)簽,因此這個(gè)段代碼成了非法代碼,因?yàn)閐ocument.write的調(diào)用書寫不正確,缺少右邊的括號(hào))。此時(shí),你可以在console中看到相關(guān)的錯(cuò)誤信息。
為了解決這個(gè)問題,我們可以對(duì)插入文本中閉合的的標(biāo)簽進(jìn)行輕微修改,對(duì)最后一個(gè)>進(jìn)行轉(zhuǎn)義,變成\>。
此時(shí)再刷新一下頁面,就可以看到預(yù)想中的結(jié)果。即頁面中僅顯示h1,彈窗阻塞了瀏覽器對(duì)HTML的解析,關(guān)閉彈窗后,瀏覽器繼續(xù)對(duì)HTML的解析并完成對(duì)頁面的渲染。
再去看看DOM的結(jié)構(gòu),會(huì)發(fā)現(xiàn)在原有的script元素后面又多了一個(gè)新的<script>元素,其中所執(zhí)行的代碼就是我們的alert("opps!!!")。
document.write使用的時(shí)機(jī)很重要
這樣看來,利用document.write來在HTML中插入標(biāo)簽非常方便,就如同讓瀏覽器在解析HTML的時(shí)候動(dòng)態(tài)得添加標(biāo)簽,而且只需要一行代碼即可,不需要使用document.createElement再將其插入到DOM中。
但為什么大家都不建議使用document.write呢?這跟document.write的實(shí)現(xiàn)機(jī)制有關(guān)。在討論之前,先看看下面的代碼:
<script>setTimeout(function(){document.write('<p>5 secs later</p>');}, 5000); </script>對(duì)之前的代碼作簡(jiǎn)單修改,這段代碼同樣是想插入一個(gè)p元素,但它是在5秒以后才執(zhí)行。
刷新頁面后,我們看到了這樣的顯示效果:
HeadTail但是5秒以后,頁面卻變成了這樣:
5 secs later原來的h1、h2甚至是script,DOCTYPE還有head(當(dāng)然,之前并沒有往head添加任何標(biāo)簽,但如果添加了,這些標(biāo)簽也會(huì)有同樣的下場(chǎng)),它們?nèi)慷疾灰娏?#xff0c;取而代之的是一個(gè)基本的html結(jié)構(gòu),它是這樣的:
<html><head></head><body><p>5 secs later</p></body> </html>這是一個(gè)全新的頁面,document.write將之前的頁面全部清除了,重新打開一頁面并在這個(gè)頁面上寫入了新的標(biāo)簽。為什么會(huì)這樣呢?
回到再文章開頭所描述文字,就會(huì)找到結(jié)果。這是因?yàn)?#xff0c;5秒以后,瀏覽器早已完成了HTML的解析,并將文檔流給關(guān)閉了。5秒后,timeout事件觸發(fā),document.write在執(zhí)行的時(shí)候發(fā)現(xiàn)文檔流已經(jīng)關(guān)閉了,就會(huì)重新調(diào)用document.open打開一個(gè)新的文檔流,而document.open的調(diào)用則會(huì)清除已有的文檔。所以,最終看到的顯示結(jié)果就是向上面那樣,之前存在的頁面都被清除掉了。
如果我們把document.write調(diào)用放到DOMCOntentLoaded或load的事件處理中,也會(huì)得到同樣的結(jié)果。
這樣看到,除非是在瀏覽器關(guān)閉文檔之前調(diào)用document.write,否則當(dāng)前頁面都會(huì)被清除。
這一個(gè)特性決定了document.write在實(shí)際開發(fā)中的應(yīng)用范圍和時(shí)機(jī)。那么,什么時(shí)候應(yīng)該使用document.write呢?
在網(wǎng)上搜集的資料看,一般在下列情景下可以利用document.write來完成某些特殊的操作:
加載需要配合JS腳本使用的外部CSS文件
利用下面的語句加載外部樣式文件:
<scirpt>document.write('<link rel="stylesheet" href="style_neads_js.css">'); </script>將所有需要用到JS的樣式都放到這個(gè)外部樣式表中,如果瀏覽器不禁用JS,那么該樣式表就會(huì)被順利加載,否則頁面就不會(huì)使用該樣式。(Don’t docwrite scripts)
在新的窗口中寫入新的頁面數(shù)據(jù)時(shí)
既然在一個(gè)已加載完成的頁面中調(diào)用document.write會(huì)重寫整個(gè)頁面,那么在一個(gè)新的窗口的空白頁面中調(diào)用這個(gè)方法,就不存在這樣的的問題了。
另外,在調(diào)用document.write,最好不要把document.open和document.close漏掉,盡管多數(shù)時(shí)候?yàn)g覽器會(huì)幫忙完成這些操作。即,一個(gè)標(biāo)準(zhǔn)的document.write應(yīng)該是這樣的:
document.open(); document.write('anthing') document.close();弊端
從某個(gè)角度說,document.write的實(shí)際功能確實(shí)很強(qiáng),能夠直接修改文檔流,但它有很多弊端:
- 在非loading階段調(diào)用document.write會(huì)清除已加載的頁面;
- document.write不能夠在XHTML中使用;
- 嵌入script中的document.write不能給任意節(jié)點(diǎn)添加子節(jié)點(diǎn),因?yàn)樗请S著DOM的構(gòu)建執(zhí)行的;
- 利用document.write寫入HTML字符串流并不是一個(gè)好方法,它有違DOM操作的概念;
- 利用document.write添加script加載外部腳本時(shí),瀏覽器的HTML解析會(huì)被script的加載所阻塞;
總結(jié)
綜合上面所描述的關(guān)于document.write的種種特點(diǎn),個(gè)人感覺還是不到迫不得已的時(shí)候,不要去使用document.write,使用不當(dāng)document.write不僅會(huì)影響頁面的性能,還容易造成各種bug。
要對(duì)DOM進(jìn)行操作時(shí),還是應(yīng)當(dāng)使用安全且對(duì)DOM的友好的API方法,以避免不必要的問題出現(xiàn)。
上述信息都是以自己做的小測(cè)試和網(wǎng)上的參考資料為基礎(chǔ)總結(jié)出來,有錯(cuò)誤的地方,歡迎大家指出,我會(huì)盡快作出修正。
參考
js中document.write的那點(diǎn)事
document.wrtie_MDN
Three JavaScript articles and one best practice
Don’t docwrite scripts
Why is document.write considered a “bad practice”?
轉(zhuǎn)載于:https://www.cnblogs.com/elcarim5efil/p/4749262.html
總結(jié)
以上是生活随笔為你收集整理的关于document.write的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jQuery选中该复选框来实现/全部取消
- 下一篇: 怎么在泰山上进行攀岩活动?