document.write()的一些坑


  這段時間在做一個廣告系統,需要用js自動生成廣告代碼,其中遇到一些問題,在這記錄下。

  第三方廣告代碼一般都是用 document.write()向頁面寫入,這次使用的時候遇到不少坑,經常會出現使用document.write()向頁面寫入的時候當前頁面被清空。這正是document.write()的特殊之處,頁面載入后瀏覽器輸出流自動關閉,此后對當前頁面進行document.write()操作將打開—個新的輸出流,它將清除當前頁面內容(包括源文檔的任何變量或值)。

  那么有哪些瀏覽器輸出流關閉的標識呢?我們首先想到的是 window.onload,在window.onload后頁面加載完成,瀏覽器輸出流必然關閉。經測試$(document).ready()中的操 作也是在瀏覽器輸出流關閉之后執行。所以用於生成代碼的document.write()不能寫在window.onload 和$(document).ready()中。除了這兩個之外有沒有其他坑呢?js生成廣告代碼中需要ajax獲取服務端的數據,ajax請求成功之后再 document.write()寫入仍然會發生覆蓋。這是因為jquery的ajax默認是異步請求,並不阻塞文檔流,當ajax請求成功之后在執行操 作,瀏覽器輸出流很可能就關閉了。這種情況可以把ajax默認請求改成同步,阻塞文檔流,防止document.write()覆蓋。

   由於第三方廣告代碼使用document.write()輸出,所有的廣告資源都在頁面載入時加載,如果頁面上第三方廣告比較多,必然會阻塞頁面加載。有 沒有辦法在使用document.write()的情況下不阻塞頁面加載呢?其實是可以的,這里就需要我們改造原生的document.write()方 法,在廣告加載完畢再把原生方法改回來。這里就不具體展開來寫,雨夜帶刀博客《讓document.write的廣告無阻塞的加載》有詳細分析,這里貼一下帶刀改造document.write()的代碼。

 1 /**
 2  * 重寫document.write實現無阻塞加載script
 3  * @param { Dom Object } textarea元素
 4  */
 5 var loadScript = function( elem ){
 6     var url = elem.value.match( /src="([\s\S]*?)"/i )[1],
 7         parent = elem.parentNode,
 8         // 緩存原生的document.write
 9         docWrite = document.write,    
10         // 創建一個新script來加載
11         script = document.createElement( 'script' ), 
12         head = document.head || 
13             document.getElementsByTagName( 'head' )[0] || 
14             document.documentElement;
15     
16     // 重寫document.write
17     document.write = function( text ){
18         parent.innerHTML = text;
19     };
20 
21     script.type = 'text/javascript';
22     script.src = url;
23     
24     script.onerror = 
25     script.onload = 
26     script.onreadystatechange = function( e ){
27         e = e || window.event;
28         if( !script.readyState || 
29         /loaded|complete/.test(script.readyState) ||
30         e === 'error'
31         ){
32 
33             // 恢復原生的document.write
34             document.write = docWrite;
35             head.removeChild( script );
36             
37             // 卸載事件和斷開DOM的引用
38             // 盡量避免內存泄漏
39             head =             
40             parent = 
41             elem =
42             script = 
43             script.onerror = 
44             script.onload = 
45             script.onreadystatechange = null;
46 
47         }
48     }
49     
50     // 加載script
51     head.insertBefore( script, head.firstChild );
52 };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM