加载文件CSS文件动态加载

在本文中,我们主要介绍加载文件的内容,自我感觉有个不错的建议和大家分享下

    前段时间究研了下JS动态加载和执行次序依附的东东,把LABJS的码源从头扒了下:LABJS浅析。对于JS加载执行以及下载监控这,目项组在这块做的西东不少,但对于CSS加载这块的量质监控,力度就小得多了。原因很简单:JS下载失败或错出,这个页面基本就废了。CSS下载失败,大部分况情下页面还是可用的,虽然会较比臭。

    但对于OPA说来,况情可能就全完不同了,CSS文件加载失败的影响对相就较比大了。

    本着命生不息折腾不已的精力,又捣腾了下CSS加载这块的内容,结果如下,鉴于天今晚上11点才放工回家在现经已很困,就直接上代码了,详细分析前面补上~

    删掉释注空行其实代码很少,关于如何测试、API调用都在头开声明白,demo可下载 件附 :)

    每日一道理
时间好比一条小溪,它能招引我们奔向生活的海洋;时间如同一叶扁舟,它将帮助我们驶向理想的彼岸;时间犹如一支画笔,它会指点我们描绘人生的画卷。
  1 /**
  2  * CSS文件加载器,主要功能:动态加载CSS文件,持支加载成完时候的调回(胜利 and 失败 况情下)
  3  * 码源实现鉴借:https://github.com/rgrove/lazyload/commit/6caf58525532ee8046c78a1b026f066bad46d32d
  4  * 更多关于CSS加载的坑的探讨,见:http://www.phpied.com/when-is-a-stylesheet-really-loaded/
  5  * 
  6  * 测试法方:1)将文件解压到服务器上(或用fiddler等地本文件替换) 2)拜访demo.html便可
  7  *
  8  * @example
  9  *   loadCSS.load('style.css');
 10  *   loadCSS.load('style.css', function(){ alert('style.css loaded'); });
 11  *   loadCSS.load('style.css', function(obj){ alert('age is '+obj.age); }, {age: 24});
 12  *   loadCSS.load(['a.css', 'b.css'], function(){ alert('a.css and b.css are all loaded'); });
 13  *
 14  * 更多说明:前目只能判断CSS文件加载事件否是成完,至于否是涌现404、5XX等,还判断不了
 15  * 曲线救国:调回里判断CSS里定义的某个款式否是存在/失效,借此判断CSS否是下载胜利,如下
 16  *   loadCSS.load('sytle.css', function(){
 17  *      var div = document.createElement('div');
 18  *      div.className = 'pre_defined_class';  //pre_defined_class 为测试用的预定义类,假设为 .pre_defined_class{display:none;}
 19  *      var value = getStyle(div, 'display');
 20  *      if(value=='none'){
 21  *        //胜利
 22  *      }else{
 23  *        //失败
 24  *      }
 25  *   })
 26  *
 27  * @version 1.0
 28  * @TODO: 1)态静加载的CSS文件的检测(否是胜利加载)2)加载配置项
 29  * @author casper  chyingp@gmail.com 
 30  *                 http://www.cnblogs.com/chyingp
 31  *                 http://www.zcool.com.cn/u/346408
 32  * 
 33  */
 34 var LoadCSS = (function () {
 35   
 36   //配置项,未实现
 37   var CFG = {
 38     POLL_INTERVAL: 50,
 39     MAX_TIME: 10
 40   };
 41   
 42   var head = document.head || document.getElementsByTagName('head')[0];
 43   var styleSheets = document.styleSheets
 44   var env = getEnv(); //获得用户代理信息,为浏览器差异化加载供给判断据依
 45   var queue = []; //CSS加载队列
 46   /*
 47     @格式1 queue队列内素元格式
 48     {
 49       urls: ['a.css', 'b.css', 'd.css'],
 50       callback: function(param){},  //urls面里有所CSS文件加载成完后的调回法方,可选
 51       obj: {age:24} //callback调回法方传入的实参
 52     }
 53    */
 54   
 55 
 56   function indexOf(arr, ele){
 57     var ret = -1;
 58     for(var i=0,len=arr.length; i<len; i++){
 59       if(arr[i]==ele) ret = i;
 60     }
 61     return ret;
 62   }  
 63 
 64   /**
 65    * @private
 66    * @description 返回用户浏览器代理信息,为判断不同浏览器供给据依
 67    * @return {Object} 格式见外部代码
 68    */
 69   function getEnv() {
 70     var ua = navigator.userAgent;
 71     var env = {};
 72 
 73     (env.webkit = /AppleWebKit\//.test(ua))
 74       || (env.ie = /MSIE/.test(ua))
 75       || (env.opera = /Opera/.test(ua))
 76       || (env.gecko = /Gecko\//.test(ua))
 77       || (env.unknown = true);
 78 
 79     return env;
 80   }
 81 
 82   /**
 83    * @private
 84    * @description gecko核内的浏览器轮询检测法方
 85    * 考参:http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
 86    * @param {HTMLElement} node style点节,node.nodeName == 'STYLE'
 87    * @param {Object} queueObj 见@格式1
 88    */
 89   function pollGecko(node, queueObj) {
 90     try {
 91 
 92       node.sheet.cssRules;
 93 
 94     } catch (ex) {
 95 
 96       node.pollCount++;
 97 
 98       if (node.pollCount < 200) {
 99 
100         setTimeout(function () { 
101           pollGecko(node, queueObj); 
102         }, 50);
103 
104       } else {
105 
106         finishLoading(node.href, queueObj);  //用不用略做些延迟,避免神一样的渲染题问??
107       
108       }
109 
110       return;
111     }
112 
113     finishLoading(node.href, queueObj);
114   }
115 
116 
117   /**
118    * @private
119    * @description webkit核内的浏览器轮询检测法方
120    * @param {HTMLElement} node link点节,node.nodeName == 'LINK'
121    * @param {Object} queueObj 见@格式1
122    */
123   function pollWebKit(node, queueObj) {
124 
125     for(var i=styleSheets.length; i>0; i--){
126     
127        if(styleSheets[i-1].href===node.href){
128         finishLoading(node.href, queueObj);
129         return;
130       }
131     }
132 
133     node.pollCount++; //轮询次数加1
134 
135     if (node.pollCount < 200) {
136       setTimeout(function(){
137         pollWebKit(node, queueObj);
138       }, 50);
139     } else {
140       finishLoading(node.href, queueObj);
141     }
142   }
143 
144   function checkSucc(className, attr, value){
145     var div = document.createElement('div');
146     div.style.cssText += 'height:0; line-height:0; visibility:hidden;';
147     div.className = className;
148     document.body.appendChild(div);
149 
150     return getComputedStyle(div, attr)==value;
151   }
152 
153   /**
154    * @description 获得点节款式值——只能获得较比简单的款式的值,一些兼容性题问不是重点,在这里不做处置,有趣兴可以看下jquery码源
155    * @param {HTMLElement} node dom点节
156    * @param {String} attr 款式名字,如display、visibility等
157    */
158   function getComputedStyle(node, attr){
159     var getComputedStyle = window.getComputedStyle;
160     if(getComputedStyle){
161       return getComputedStyle(node, null)[attr];
162     }else if(node.currentStyle){
163       return node.currentStyle[attr];
164     }else{
165       return node.style[attr];
166     }
167   }
168 
169   /**
170    * @private
171    * @description url对应的CSS文件加载成完时的调回(404也括包在内)
172    * @param {String} url CSS文件的url
173    * @param {Object} queueObj 见@格式1
174    */
175   function finishLoading(url, queueObj){
176       var index = indexOf(queueObj.urls, url);
177       queueObj.urls.splice(index, 1);
178 
179       if(!queueObj.urls.length){
180         queueObj.callback(queueObj.obj);
181 
182         index = indexOf(queue, queueObj);
183         queue.splice(index, 1);
184       }
185   }
186 
187   /**
188    * @description 加载CSS的法方
189    * @param {Array} urls 加载的CSS文件名队列
190    * @param {Function} [callback] CSS文件队列全体加载完的调回
191    * @param {Object} obj callback的数参
192    * @param {Object} context
193    * @return {Undefined}
194    */
195   function loadCSS(urls, callback, obj) {
196     var queueObj = {
197       urls: urls,
198       callback: callback,
199       obj: obj
200     }
201     queue.push(queueObj);
202     
203     var pendingUrls = queueObj.urls;
204     for (var i = 0, len = pendingUrls.length; i < len; ++i) {
205       
206       var url = pendingUrls[i];
207       var node ;
208       if(env.gecko){
209         node = document.createElement('style');
210       }else{
211         node = document.createElement('link');
212         node.rel = 'stylesheet';
213         node.href = url;
214       }
215       //node.setAttribute('charset', 'utf-8');  //设不设置有木有影响,持保存立场
216       
217       if (env.gecko || env.webkit) {  //老版本webkit、gecko不持支onload
218         
219         node.pollCount = 0;
220         queueObj.urls[i] = node.href; //轮询判断的时候用到,因为不同浏览器面里取到的node.href值会不一样,有的只有文件名,有的是整完文件名?(对相路径、绝对路径)          
221         
222         if (env.webkit) {  //之所以要用轮询,前面探讨,@TODO: 新版本的webkit经已持支onload、onerror,优化下?
223         
224           pollWebKit(node, queueObj);
225         
226         } else {
227           
228           node.innerHTML = '@import "' + url + '";';  //为什么这样做,猛点击这里:http://www.phpied.com/when-is-a-stylesheet-really-loaded/
229           pollGecko(node, queueObj);
230         }
231 
232       } else {
233         
234         node.onload = node.onerror = function(){
235           finishLoading(this.href, queueObj);
236         };
237       }
238 
239       head.appendChild(node);
240     }
241   }
242 
243   //---------------------- 对外口接!---------------------------
244   return {
245 
246     /**
247      * @description 加载CSS文件
248      * 斟酌:胜利调回,错误调回离开?
249      * @param {Array|String} urls 要加载的CSS文件的文件名(对相路径,或绝对路径),比如:'style.css', ['style.css', 'test.css']
250      * @param {Function} [callback] 可选:文件加载成完后的调回(胜利;或失败,如404、500等)
251      * @param {Object} [obj] 可选:调回执行时传入的数参
252      */
253     load: function (urls, callback, obj) {
254       loadCSS([].concat(urls), callback || function(){}, obj || {});
255     }
256 
257   };
258 })();
 >>>我是件附,赶忙猛点击

文章结束给大家分享下程序员的一些笑话语录: 神灯新篇
一个程序员在海滩上发现了一盏神灯。他在灯上擦了几下,一个妖怪就从灯里跳出来说:“我是世界上法术最强的妖怪。我可以实现你的任何梦想,但现在,我只能满足你一个愿望。”程序员摊开了一幅中东地图说:“我想让中东得到永久的和平。”妖怪答道:“哦,我没办法。自打创世纪以来,那里的战火就没有停息过。这世上几乎没有我办不到的事,但这件事除外。”程序员于是说:“好吧,我是一个程序员,为许多用户编写过程序。你能让他们把需求表述得更清楚些,并且让我们的软件项目有那么一两次按进度按成本完成吗?”妖怪说:“唔,我们还是来看中东地图吧。”


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值