欢迎您访问我爱IT技术网,今天小编为你分享的javascript教程:【重写document.write实现无阻塞加载js广告(补充)】,下面是详细的讲解!
重写document.write实现无阻塞加载js广告(补充)
无阻塞加载javascript,对于页面性能优化有很大的作用,这样能有效的减少js对页面加载的阻塞。特别是一些广告js文件,由于广告内容有可能是富媒体,更是很可能成为你页面加载提速的瓶颈,高性能javascript告诉我们,同学,提升你的网页速度,就无阻塞地加载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代码
document.write('<img src="http://img.jb51.net/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广告:
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=http://www.jb51.net/article/_this.url;
script.type='text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
},
finished: function(){
document.write=this.dw;
this.callback.apply();
}
};
页面调用代码:
var loadScript=new LoadADScript('ad.js','msat-adwrap',function(){ console.log('msat-adwrap'); });
loadScript.startLoad();
var loadScript=new LoadADScript('ad2.js','msat-adwrap',function(){ console.log('msat-adwrap2'); });
loadScript.startLoad();
var loadScript=new LoadADScript('ad3.js','msat-adwrap',function(){ console.log('msat-adwrap3'); });
loadScript.startLoad();
广告js代码
//ad.js
document.write('<img src="http://www.52ij.com/uploads/allimg/160212/1306235621-1.gif" alt="Logo">');
//ad2.js
document.write('<img src="http://www.52ij.com/uploads/allimg/160212/1306231529-2.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页面代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>new_file</title>
<script type="text/javascript" src="http://www.jb51.net/article/loadscript.js"></script>
</head>
<body>
<div id="msat-adwrap"></div>
<div id="msat-adwrap2"></div>
<script type="text/javascript">
loadScript.add({
url:'ad.js',
container: 'msat-adwrap',
callback:function(){ console.log('msat-adwrap'); }
}).add({
url:'ad2.js',
container: 'msat-adwrap2',
callback:function(){ console.log('msat-adwrap2'); }
}).add({//google adsense
url:'http://pagead2.googlesyndication.com/pagead/show_ads.js',
container: 'msat-adwrap',
init: function(){
google_ad_client="ca-pub-2152294856721899";
google_ad_slot="3929903770";
google_ad_width=250;
google_ad_height=250;
},
callback:function(){ console.log('msat-adwrap3'); }
}).execute();
</script>
</body>
</html>
loadscript.js源代码
var loadScript=( function() {
var adQueue=[], dw=document.write;
//缓存js自身的document.write
function LoadADScript(url, container, 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=http://www.jb51.net/article/_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(adObj.url, adObj.container, adObj.init, adObj.callback));
return this;
},
execute : function() {
if(adQueue.length > 0) {
adQueue[0].startLoad();
}
}
};
}());
关于重写document.write实现无阻塞加载js广告(补充)的用户互动如下:
相关问题:动态调用包含document.write的js文件,动态调用外...
答:document.write()方法可以用在两个方面:页面载入过程中用实时脚本创建页面内容,以及用延时脚本创建本窗口或新窗口的内容。该方法需要一个字符串参数,它是写到窗口或框架中的HTML内容。这些字符串参数可以是变量或值为字符串的表达式,写入的... >>详细
相关问题:JS中document.write有破坏性,DOM加载完成后再执行...
答:也是基于js的appendChild之类的方法实现的,具体实现代码有兴趣你可以看看jq源码。 >>详细
相关问题:关于js中document.write()问题
答:doucment.write 就是调用了 document 的写方法。 整个页面都是document 。 意思就是document被重写了。 当执行document.write(document.getElementById("DIV_top").style.height); 这句后, 页面被重写,div就没有了。所以下面那句就 因为找不到... >>详细
- 【Ajax】jQuery 学习第六课 实现一个Ajax的TreeVi
- 【extjs】extjs每个组件要设置唯一的ID否则会出错
- 【bootstrap3】基于bootstrap3和jquery的分页插件
- 【hover】jQuery控制图片的hover效果(smartRollo
- 【div】div浮层 滚动条移动 位置保持不变的4种方
- 【Cookie】Cookie 小记
- 【arguments】JavaScript的arguments对象应用示例
- 【ECMAScript5】ECMAScript5中的对象存取器属性:
- 【function】JavaScript function 的 length 属性
- 【ExtJs】ExtJs动态生成treepanel的Json格式-tree
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
