微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

于是便有一下代码出现。

rush:js;"> (function() { var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s,x); })();

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

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

先看看广告js代码

代码如下:
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广告:

rush:js;"> function LoadADScript(url,container,callback){ this.dw = document.write; this.url = url; this.containerObj = (typeof container == 'string'?document.getElementById(container):container); this.callback = callback || function(){}; }

LoadADScript.prototype = {
startLoad: function(){
var script = document.createElement('script'),_this = this;

  if(script.readyState){ //IE
    script.onreadystatechange = function(){
    if (script.readyState == "loaded" || script.readyState == "complete"){
      script.onreadystatechange = null;
      _this.finished();
    }
  };
  }else{ //Other
    script.onload = function(){
      _this.finished();
    };
  }

  document.write = function(ad){
    var html = _this.containerObj.innerHTML;
    _this.containerObj.innerHTML = html + ad;
  }

  script.src = _this.url;
  script.type = 'text/javascript';
  document.getElementsByTagName('head')[0].appendChild(script);
},finished: function(){
  document.write = this.dw;
  this.callback.apply();
}

};

页面调用代码

rush:js;"> var loadScript = new LoadADScript('ad.js','msat-adwrap',function(){ console.log('msat-adwrap'); }); loadScript.startLoad();

var loadScript = new LoadADScript('ad2.js',function(){ console.log('msat-adwrap2'); });
loadScript.startLoad();

var loadScript = new LoadADScript('ad3.js',function(){ console.log('msat-adwrap3'); });
loadScript.startLoad();

广告js代码

rush:js;"> //ad.js document.write('logo_small.gif" alt="logo">');

//ad2.js
document.write('<img src="http://www.baidu.com/img/baidu_sylogo1.gif" width="270" height="129" usemap="#mp">');

//ad3.js
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页面代码:

rush:js;"> new_file

loadscript.js源代码

var loadScript = ( function() {
var adQueue = [],dw = document.write;
//缓存js自身的document.write

function LoadADScript(url,init,callback) {
this.url = url;
this.containerObj = ( typeof container == 'string' ? document.getElementById(container) : container);
this.init = init ||
function() {
};

this.callback = callback ||
function() {
};

}

LoadADScript.prototype = {
startLoad : function() {
var script = document.createElement('script'),_this = this;

  _this.init.apply();

  if(script.readyState) {//IE
    script.onreadystatechange = function() {
      if(script.readyState == "loaded" || script.readyState == "complete") {
        script.onreadystatechange = null;
        _this.startNext();
      }
    };
  } else {//Other
    script.onload = function() {
      _this.startNext();
    };
  }
  //重写document.write
  document.write = function(ad) {
    var html = _this.containerObj.innerHTML;
    _this.containerObj.innerHTML = html + ad;
  }

  script.src = _this.url;
  script.type = 'text/javascript';
  document.getElementsByTagName('head')[0].appendChild(script);
},finished : function() {
  //还原document.write
  document.write = this.dw;
},startNext : function() {
  adQueue.shift();
  this.callback.apply();
  if(adQueue.length > 0) {
    adQueue[0].startLoad();
  } else {
    this.finished();
  }
}

};

return {
add : function(adobj) {
if(!adobj)
return;

  adQueue.push(new LoadADScript(a<a href="https://www.jb51.cc/tag/dob/" target="_blank" class="keywords">dob</a>j.url,a<a href="https://www.jb51.cc/tag/dob/" target="_blank" class="keywords">dob</a>j.container,a<a href="https://www.jb51.cc/tag/dob/" target="_blank" class="keywords">dob</a>j.init,a<a href="https://www.jb51.cc/tag/dob/" target="_blank" class="keywords">dob</a>j.callback));
  return this;
},execute : function() {
  if(adQueue.length > 0) {
    adQueue[0].startLoad();
  }
}

};
}());

原文地址:https://www.jb51.cc/js/56971.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐