首页 > 语言 > JavaScript > 正文

重写document.write实现无阻塞加载js广告(补充)

2024-05-06 16:11:56
字体:
来源:转载
供稿:网友

这篇文章主要介绍了重写document.write实现无阻塞加载js广告,需要的朋友可以参考下

无阻塞加载javascript,对于页面性能优化有很大的作用,这样能有效的减少js对页面加载的阻塞。特别是一些广告js文件,由于广告内容有可能是富媒体,更是很可能成为你页面加载提速的瓶颈,高性能javascript告诉我们,同学,提升你的网页速度,就无阻塞地加载JS吧。

于是便有一下代码出现。
 

  1. (function() { 
  2. var s = document.createElement('script'); 
  3. s.type = 'text/javascript'
  4. s.async = true
  5. s.src = 'http://yourdomain.com/script.js'
  6. var x = document.getElementsByTagName('script')[0]; 
  7. x.parentNode.insertBefore(s, x); 
  8. })(); 

上边都是大家熟悉的,看过书的同学都知道这样无阻塞加载的好处,效果挺不错的,当此等无阻塞脚本遇到一般js广告就来了写问题——广告代码出现在HTML里面了却不显示广告。

 

纳尼?HTML出来了不渲染到页面上?

先看看广告js代码

复制代码代码如下:


 

  1. document.write('<img src="http://www.vevb.com/logo_small.gif" alt="Logo">'); 

代码挺简单就一个document.write输出HTML代码(相信很多广告商的广告都这样),页面不显示广告问题在哪里呢? 问题就在这个document.write。为什么?先w3schools看看document.write的定义很使用吧。

定义和用法

write() 方法可向文档写入 HTML 表达式或 JavaScript 代码。

可列出多个参数(exp1,exp2,exp3,...) ,它们将按顺序被追加到文档中。

方法:

一是在使用该方在文档中输出 HTML,另一种是在调用该方法的的窗口之外的窗口、框架中产生新文档。在第二种情况中,请务必使用 close() 方法来关闭文档。

但其原理是在页面流输入过程中执行,一旦页面加载完毕,再次调用 document.write(),会隐式地调用 document.open() 来擦除当前文档并开始一个新的文档。也就是说如果在HTML加载完后我们再使用document.write会檫除之前生成html,而显示document.write输出的内容。

而我们例子中在页面加载完后在在html中输出document.write,就不会被执行了。问题知道了,原理知道了,那怎么解决这个问题呢?

异步利用ajax,行不同,很多广告文件都是第三方的,在不同域名下,存在跨域问题,而且不能我们控制其代码的输出。在这种情况下我们想到了一个办法就是重写掉document.write,在js文件加载结束后再把document.write重写回去。看代码。

第一版本无阻塞加载js广告:

  1. function LoadADScript(url, container, callback){ 
  2. this.dw = document.write; 
  3. this.url = url; 
  4. this.containerObj = (typeof container == 'string'?document.getElementById(container):container); 
  5. this.callback = callback || function(){}; 
  6.  
  7. LoadADScript.prototype = { 
  8. startLoad: function(){ 
  9. var script = document.createElement('script'), 
  10. _this = this
  11.  
  12. if(script.readyState){ //IE 
  13. script.onreadystatechange = function(){ 
  14. if (script.readyState == "loaded" || script.readyState == "complete"){ 
  15. script.onreadystatechange = null
  16. _this.finished(); 
  17. }; 
  18. }else//Other 
  19. script.onload = function(){ 
  20. _this.finished(); 
  21. }; 
  22.  
  23. document.write = function(ad){ 
  24. var html = _this.containerObj.innerHTML; 
  25. _this.containerObj.innerHTML = html + ad; 
  26.  
  27. script.src = _this.url; 
  28. script.type = 'text/javascript'
  29. document.getElementsByTagName('head')[0].appendChild(script); 
  30. }, 
  31. finished: function(){ 
  32. document.write = this.dw; 
  33. this.callback.apply(); 
  34. }; 


页面调用代码:

  1. var loadScript = new LoadADScript('ad.js','msat-adwrap',function(){ console.log('msat-adwrap'); }); 
  2. loadScript.startLoad(); 
  3.  
  4. var loadScript = new LoadADScript('ad2.js','msat-adwrap',function(){ console.log('msat-adwrap2'); }); 
  5. loadScript.startLoad(); 
  6.  
  7. var loadScript = new LoadADScript('ad3.js','msat-adwrap',function(){ console.log('msat-adwrap3'); }); 
  8. loadScript.startLoad(); 


广告js代码

  1. //ad.js 
  2. document.write('<img src="http://images.cnblogs.com/logo_small.gif" alt="Logo">'); 
  3.  
  4. //ad2.js 
  5. document.write('<img src="http://www.baidu.com/img/baidu_sylogo1.gif" width="270" height="129" usemap="#mp">'); 
  6.  
  7. //ad3.js 
  8. document.write('<img alt="Google" height="95" id="hplogo" src="http://www.google.com/images/srpr/logo3w.png" width="275">'); 


第一版本的问题是在多个文件调用的时候,会出现一些问题:

1. 由于文件加载的速度不一样,导致可能有些先加载有些后加载,也就是无序的,而且很多时候我们需要的是有序的。比如我们需要先加载第一屏的广告。

2. 想有些广告需要前置设置一些参数的,例如google adsense

为了解决这两个问题好进一步修改成最终无阻塞加载js版本。

HTML页面代码:

 


  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4. <meta charset="utf-8" /> 
  5. <title>new_file</title> 
  6. <script type="text/javascript" src="loadscript.js"></script> 
  7. </head> 
  8. <body> 
  9. <div id = "msat-adwrap"></div> 
  10. <div id = "msat-adwrap2"></div> 
  11. <script type="text/javascript"
  12. loadScript.add({ 
  13. url:'ad.js'
  14. container: 'msat-adwrap'
  15. callback:function(){ console.log('msat-adwrap'); } 
  16. }).add({ 
  17. url:'ad2.js'
  18. container: 'msat-adwrap2'
  19. callback:function(){ console.log('msat-adwrap2'); } 
  20. }).add({//google adsense 
  21. url:'http://pagead2.googlesyndication.com/pagead/show_ads.js'
  22. container: 'msat-adwrap'
  23. init: function(){ 
  24. google_ad_client = "ca-pub-2152294856721899"
  25. /* 250x250 rich */ 
  26. google_ad_slot = "3929903770"
  27. google_ad_width = 250; 
  28. google_ad_height = 250; 
  29. }, 
  30. callback:function(){ console.log('msat-adwrap3'); } 
  31. }).execute(); 
  32. </script> 
  33. </body> 
  34. </html> 

 

loadscript.js源代码

  1. /** 
  2. * 无阻塞加载广告 
  3. * @author Arain.Yu 
  4. */ 
  5.  
  6. var loadScript = ( function() { 
  7. var adQueue = [], dw = document.write; 
  8. //缓存js自身的document.write 
  9.  
  10. function LoadADScript(url, container, init, callback) { 
  11. this.url = url; 
  12. this.containerObj = ( typeof container == 'string' ? document.getElementById(container) : container); 
  13. this.init = init || 
  14. function() { 
  15. }; 
  16.  
  17.  
  18. this.callback = callback || 
  19. function() { 
  20. }; 
  21.  
  22.  
  23.  
  24. LoadADScript.prototype = { 
  25. startLoad : function() { 
  26. var script = document.createElement('script'), _this = this
  27.  
  28. _this.init.apply(); 
  29.  
  30. if(script.readyState) {//IE 
  31. script.onreadystatechange = function() { 
  32. if(script.readyState == "loaded" || script.readyState == "complete") { 
  33. script.onreadystatechange = null
  34. _this.startNext(); 
  35. }; 
  36. else {//Other 
  37. script.onload = function() { 
  38. _this.startNext(); 
  39. }; 
  40. //重写document.write 
  41. document.write = function(ad) { 
  42. var html = _this.containerObj.innerHTML; 
  43. _this.containerObj.innerHTML = html + ad; 
  44.  
  45. script.src = _this.url; 
  46. script.type = 'text/javascript'
  47. document.getElementsByTagName('head')[0].appendChild(script); 
  48. }, 
  49. finished : function() { 
  50. //还原document.write 
  51. document.write = this.dw; 
  52. }, 
  53. startNext : function() { 
  54. adQueue.shift(); 
  55. this.callback.apply(); 
  56. if(adQueue.length > 0) { 
  57. adQueue[0].startLoad(); 
  58. else { 
  59. this.finished(); 
  60. }; 
  61.  
  62. return { 
  63. add : function(adObj) { 
  64. if(!adObj) 
  65. return
  66.  
  67. adQueue.push(new LoadADScript(adObj.url, adObj.container, adObj.init, adObj.callback)); 
  68. return this
  69. }, 
  70. execute : function() { 
  71. if(adQueue.length > 0) { 
  72. adQueue[0].startLoad(); 
  73. }; 
  74. }()); 
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选