Js判断CSS文件加载完毕的具体实现


Posted in Javascript onJanuary 17, 2014

要判断这个 CSS 文件是否加载完毕,各个浏览器的做法差异比较大,这次要说IE浏览器做的不错,我们可以直接通过onload方法来处理CSS加载完成以后的处理:

// 代码节选至seajs
function styleOnload(node, callback) {
    // for IE6-9 and Opera
    if (node.attachEvent) {
      node.attachEvent('onload', callback);
      // NOTICE:
      // 1. "onload" will be fired in IE6-9 when the file is 404, but in
      // this situation, Opera does nothing, so fallback to timeout.
      // 2. "onerror" doesn't fire in any browsers!
    }
}

很遗憾,这次在其他的浏览器中,想判断CSS是否加载完成就不是那么方便了,FF,webkit可以通过node.sheet.cssRules属性是否存在来判断是否加载完毕。而且需要使用setTimeout间隔事件轮询:

// 代码节选至seajs 
function poll(node, callback) {
    if (callback.isCalled) {
      return;
    }
    var isLoaded = false;
    if (/webkit/i.test(navigator.userAgent)) {//webkit
      if (node['sheet']) {
        isLoaded = true;
      }
    }
    // for Firefox
    else if (node['sheet']) {
      try {
        if (node['sheet'].cssRules) {
          isLoaded = true;
        }
      } catch (ex) {
        // NS_ERROR_DOM_SECURITY_ERR
        if (ex.code === 1000) {
          isLoaded = true;
        }
      }
    }
    if (isLoaded) {
      // give time to render.
      setTimeout(function() {
        callback();
      }, 1);
    }
    else {
      setTimeout(function() {
        poll(node, callback);
      }, 1);
    }
  } setTimeout(function() {
     poll(node, callback);
}, 0);

SeaJS给出的完整的处理是这样的:

function styleOnload(node, callback) {
    // for IE6-9 and Opera
    if (node.attachEvent) {
      node.attachEvent('onload', callback);
      // NOTICE:
      // 1. "onload" will be fired in IE6-9 when the file is 404, but in
      // this situation, Opera does nothing, so fallback to timeout.
      // 2. "onerror" doesn't fire in any browsers!
    }
    // polling for Firefox, Chrome, Safari
    else {
      setTimeout(function() {
        poll(node, callback);
      }, 0); // for cache
    }
  }
  function poll(node, callback) {
    if (callback.isCalled) {
      return;
    }
    var isLoaded = false;
    if (/webkit/i.test(navigator.userAgent)) {//webkit
      if (node['sheet']) {
        isLoaded = true;
      }
    }
    // for Firefox
    else if (node['sheet']) {
      try {
        if (node['sheet'].cssRules) {
          isLoaded = true;
        }
      } catch (ex) {
        // NS_ERROR_DOM_SECURITY_ERR
        if (ex.code === 1000) {
          isLoaded = true;
        }
      }
    }
    if (isLoaded) {
      // give time to render.
      setTimeout(function() {
        callback();
      }, 1);
    }
    else {
      setTimeout(function() {
        poll(node, callback);
      }, 1);
    }
  }
// 我的动态创建LINK函数
function createLink(cssURL,lnkId,charset,media){ 
    var head = document.getElementsByTagName('head')[0],
        linkTag = null; if(!cssURL){
     return false;
 }
    linkTag = document.createElement('link');
 linkTag.setAttribute('id',(lnkId || 'dynamic-style'));
 linkTag.setAttribute('rel','stylesheet');
 linkTag.setAttribute('charset',(charset || 'utf-8'));
 linkTag.setAttribute('media',(media||'all'));
 linkTag.setAttribute('type','text/css');
    linkTag.href = cssURL; 
    head.appendChild(linkTag); 
}
function loadcss(){
    var styleNode = createLink('/wp-content/themes/BlueNight/style.css');
    styleOnload(styleNode,function(){
        alert("loaded");
    });
}

在看到seajs的代码的时候,我立刻想起了我看到Diego Perini的另一个解决方案:
/*
 * Copyright (C) 2010 Diego Perini
 * All rights reserved.
 *
 * cssready.js - CSS loaded/ready state notification
 *
 * Author: Diego Perini <diego.perini at gmail com>
 * Version: 0.1
 * Created: 20100616
 * Release: 20101104
 *
 * License:
 *  https://3water.com * Download:
 *  http://javascript.nwbox.com/cssready/cssready.js
 */
function cssReady(fn, link) {
  var d = document,
  t = d.createStyleSheet,
  r = t ? 'rules' : 'cssRules',
  s = t ? 'styleSheet' : 'sheet',
  l = d.getElementsByTagName('link');
  // passed link or last link node
  link || (link = l[l.length - 1]);
  function check() {
    try {
      return link && link[s] && link[s][r] && link[s][r][0];
    } catch(e) {
      return false;
    }
  }
  (function poll() {
    check() && setTimeout(fn, 0) || setTimeout(poll, 100);
  })();
}

其实,如果你读过jQuery的domready事件的判断的代码,原理也类似。也是通过setTimeout轮询的方式来判断DOM节点是否加载完毕。
还有,Fackbook则是通过在动态创建的CSS样式中包含一个固定的样式,例如#loadcssdom,loadcssdom就是一个高度为1px样式。然后动态创建一个DOM对象,添加这个loadcssdom样式。然后也是setTimeout轮询loadcssdo是否已经有1px的高度了。这个处理方式的解决方案,大家可以下《CSSP: Loading CSS with Javascript ? and getting an onload callback.》
而《JavaScript Patterns》的作者Stoyan则在他的博客里,比较详细的说明了《When is a stylesheet really loaded?》。
看完了这些,你可能会感叹:汗,判断CSS是否加载完毕,目前还真不是那么容易!其实我这里算是一个抛砖引玉,因为开发中,除了动态加载CSS,我们还要动态加载JavaScript,动态加载HTML的操作,有空我也会写关于动态加载JavaScript的相关内容,不过在那之前,我建议你看看这些:
    《ensure ? Ensure JavaScripts/HTML/CSS are loaded on-demand when needed》,这个库是专门处理动态加载HTML,CSS,JavaScript的。就像作者介绍的那样:
        ensure is a tiny JavaScript library that provides a handy function ensure which allows you to load JavaScript, HTML, CSS on-demand, and then execute your code. ensure 3water.com ensures that the relevant JavaScript and HTML snippets are already in the browser DOM before executing your code that uses them.
    《Tell CSS that JavaScript is available ASAP》
    看完这个后,你可能就不会纠结:When you're styling parts of a web page that will look and work differently depending on whether JavaScript is available or not。
好了,这次就说这么多了,希望对对大家的开发和学习有帮助!

Javascript 相关文章推荐
javascript 处理事件绑定的一些兼容写法
Dec 24 Javascript
JavaScript获取图片像素颜色并转换为box-shadow显示
Mar 11 Javascript
JavaScript常见的五种数组去重的方式
Dec 15 Javascript
JavaScript中的工厂函数(推荐)
Mar 08 Javascript
基于VuePress 轻量级静态网站生成器的实现方法
Apr 17 Javascript
apicloud拉起小程序并传递参数的方法示例
Nov 21 Javascript
详解Vue组件之作用域插槽
Nov 22 Javascript
vue实现数据控制视图的原理解析
Jan 07 Javascript
Javascript模块化机制实现原理详解
Apr 02 Javascript
微信小程序wx.getUserInfo授权获取用户信息(头像、昵称)的实现
Aug 19 Javascript
详解vue3中组件的非兼容变更
Mar 03 Vue.js
使用Vue.js和MJML创建响应式电子邮件
Mar 23 Vue.js
js使用eval解析json(js中使用json)
Jan 17 #Javascript
js window.open弹出新的网页窗口
Jan 16 #Javascript
jQuery$命名冲突怎么办如何解决
Jan 16 #Javascript
jQuery获得内容和属性示例代码
Jan 16 #Javascript
jQuery 追加元素的方法如append、prepend、before
Jan 16 #Javascript
jQuery 设置 CSS 属性示例介绍
Jan 16 #Javascript
jQuery 滑动方法slideDown向下滑动元素
Jan 16 #Javascript
You might like
PHP入门
2006/10/09 PHP
php+ajax实现带进度条的上传图片功能【附demo源码下载】
2016/09/14 PHP
深入分析PHP设计模式
2020/06/15 PHP
js函数中onmousedown和onclick的区别和联系探讨
2013/05/19 Javascript
JS将表单导出成EXCEL的实例代码
2013/11/11 Javascript
JavaScript获取客户端计算机硬件及系统等信息的方法
2014/01/02 Javascript
深入理解JS中的变量及作用域、undefined与null
2014/03/04 Javascript
bootstrap导航条实现代码
2016/12/28 Javascript
详解微信小程序开发之——wx.showToast(OBJECT)的使用
2017/01/18 Javascript
nodejs实现超简单生成二维码的方法
2018/03/17 NodeJs
微信开发之企业付款到银行卡接口开发的示例代码
2018/09/18 Javascript
JavaScript判断数组类型的方法
2019/10/23 Javascript
webpack 最佳配置指北(推荐)
2020/01/07 Javascript
python根据开头和结尾字符串获取中间字符串的方法
2015/03/26 Python
在Python中使用matplotlib模块绘制数据图的示例
2015/05/04 Python
python基础教程之匿名函数lambda
2017/01/17 Python
Python单例模式的两种实现方法
2017/08/14 Python
Django中使用Celery的方法示例
2018/11/29 Python
Python常见的pandas用法demo示例
2019/03/16 Python
Python装饰器使用你可能不知道的几种姿势
2019/10/25 Python
20行Python代码实现视频字符化功能
2020/04/13 Python
pytorch判断是否cuda 判断变量类型方式
2020/06/23 Python
使用Python操作MySQL的小技巧
2020/09/10 Python
Python 调用C++封装的进一步探索交流
2021/03/04 Python
HTML5拖拽功能实现的拼图游戏
2018/07/31 HTML / CSS
The North Face北面荷兰官网:美国著名户外品牌
2019/10/16 全球购物
日语专业推荐信
2013/11/12 职场文书
体育教育个人自荐信范文
2013/12/01 职场文书
自我鉴定注意事项
2014/01/19 职场文书
保护环境倡议书500字
2014/05/19 职场文书
四风对照检查材料思想汇报
2014/09/20 职场文书
给学校的建议书400字
2015/09/14 职场文书
MySQL千万级数据表的优化实战记录
2021/08/04 MySQL
Python GUI编程之tkinter 关于 ttkbootstrap 的使用详解
2022/03/03 Python
Redis基本数据类型List常用操作命令
2022/06/01 Redis
5个实用的JavaScript新特性
2022/06/16 Javascript