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 };

 

posted @ 2014-12-30 16:23  特雷西one  阅读(13335)  评论(0编辑  收藏  举报