模拟jQuery中的ready方法及实现按需加载css,js实例代码

 更新时间:2013年09月27日 16:18:12   作者:  
这篇文章介绍了模拟jQuery中的ready方法及实现按需加载css,js实例代码,有需要的朋友可以参考一下
一、ready函数的实现
经常用jQuery类库或其他类库中的ready方法,有时候想想它们到底是怎么实现的,但是看了一下jQuery中的源码,涉及到的模块比较多,(水平有限)代码比较难看懂;自己结合了一些书籍内容,总结一下。
先说一下ready函数的实现思路:
变量ready通过表达式赋值,右侧为一个自执行匿名函数,在这个匿名函数中,首先为各个浏览器的事件绑定处理函数,并为isReady赋值(根据事件异步处理程序来确定),然后返回一个传参闭包,在闭包中,主要判断isReady值来执行操作,如果dom结构准备就绪(isReady === true),执行回调,否则将回调加入到要执行的队列(funs)中,待事件处理程序执行时,循环遍历队列(funs),并依次执行队列中的函数,执行完队列中的函数后,还需要清除队列(funs = null)。
复制代码 代码如下:

var ready = (function(){
    var isReady = false,
    funs = [];
    function handle (e) {
        if ( isReady ) {
            return;
        }
        if ( e.type === 'readystatechange' && (document.readyState !== 'interactive' && document.readyState !== 'complete') ) {
            return;
        }
        for ( var i = 0; i < funs.length; i++ ) {
            funs[i].call(document);
        }
        isReady = true;
        funs = null;
    }
    if ( document.addEventListener ) {
        document.addEventListener( 'DOMContentLoaded', handle, false );
        document.addEventListener( 'readystatechange', handle, false );
        document.addEventListener( 'load', handle, false );
    }
    else if ( document.attachEvent ) {
        document.attachEvent( 'onreadystatechange', handle );
        document.attachEvent( 'onload', handle );
    }
    return function ready (callback) {
        if ( isReady ) {
            callback.call(document);
        }
        else {
            funs.push(callback);
        }
    };
}());

PS:
该函数代码参照于权威指南书籍,唯一不同的是,多加了一个判断document.readyState !== 'interactive'
复制代码 代码如下:

if ( e.type === 'readystatechange' && (document.readyState !== 'interactive' && document.readyState !== 'complete') ) {
    return;
}

在各个浏览器中交互和完成状态出现顺序并不能保证一致,这取决于浏览器及页面的内容,多加了这个判断document.readyState !== 'interactive'的话,
意思是不管哪个阶段先出现,代码都能更早的执行。
二、按需加载css,js
参照了jQuery源码,写了一个type函数,返回参数类型。
复制代码 代码如下:

/**
 *
 * 判断参数类型
 * createTime: 2013/9/18
 *
 */
function type (obj) {
    var classTypes, objectTypes;
    if ( obj == null ) {
        return String(obj);
    }
    classTypes = {};
    objectTypes = ('Boolean Number String Function Array Date RegExp Object Error').split(' ');
    for ( var i = 0, len = objectTypes.length; i < len; i++ ) {
        classTypes[ '[object ' + objectTypes[i] + ']' ] = objectTypes[i].toLowerCase();
    }
    if ( typeof obj === 'object' || typeof obj === 'function' ) {
        var key = Object.prototype.toString.call(obj);
        return classTypes[key];
    }
    return typeof obj;
}

复制代码 代码如下:

// css按需加载
function loadCss (cssUrl, callback) {
    var elem, bl,
        isExecuted = false; // 防止在ie9中,callback执行两次
    if ( cssUrl == null ) {
        return String(cssUrl);
    }
    elem = document.createElement('link'),
    elem.rel = 'stylesheet';
    if ( type(callback) === 'function' )  {
        bl = true;
    }
    // for ie
    function handle() {
        if ( elem.readyState === 'loaded' || elem.readyState === 'complete' ) {
            if (bl && !isExecuted) {
                callback();
                isExecuted = true;
            }
            elem.onreadystatechange = null;
        }
    }
    elem.onreadystatechange = handle;
    // for 非ie
    if (bl && !isExecuted) {
        elem.onload = callback;
        isExecuted = true;
    }
    elem.href = cssUrl;
    document.getElementsByTagName('head')[0].appendChild(elem);
}
// js按需加载
function loadScript(scriptUrl, callback) {
    var elem, bl,
        isExecuted = false; // 防止在ie9中,callback执行两次
    if (scriptUrl == null) {
        return String(fn);
    }
    elem = document.createElement('script');
    if ( type(callback) === 'function' )  {
        bl = true;
    }
    // for ie
    function handle(){
        var status = elem.readyState;
        if (status === 'loaded' || status === 'complete') {
            if (bl && !isExecuted) {
                callback();
                isExecuted = true;
            }
            elem.onreadystatechange = null;
        }
    }
    elem.onreadystatechange = handle;
    // for 非ie
    if (bl && !isExecuted) {
        elem.onload = callback;
        isExecuted = true;
    }
    elem.src = scriptUrl;
    document.getElementsByTagName('head')[0].appendChild(elem);
}

PS: 在判断link,script元素是否加载完毕,主要依靠load事件;而在ie9以下浏览器中,并没有load事件,ie为它们都添加了一个readystatechange事件,通过判断
元素的readyState状态确定元素是否已经加载完毕;而奇怪的是,在ie9(还可能存在其他浏览器版本)中,元素既有load事件又有readystatechange事件,因此在代码中添加了一个变量isExecuted,如果执行过回调,那么就不再执行,避免回调执行两次。
三、调用方式
复制代码 代码如下:

loadCss('https://www.jb51.net/apps/tbtx/miiee/css/base.css', function(){
    console.log('css加载完毕');
});
loadScript('https://www.jb51.net/apps/tbtx/miiee/js/jQuery.js', function(){
    console.log('js加载完毕');
});
ready(function(){
    console.log('dom is ready!');
});

相关文章

  • 基于Jquery和html5实现炫酷的3D焦点图动画

    基于Jquery和html5实现炫酷的3D焦点图动画

    这篇文章主要介绍了基于Jquery和html5实现炫酷的3D焦点图动画的相关资料,焦点图中的图片利用了CSS3的相关特性实现图片倾斜效果,从而让图片出现3D的视觉效果,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • jquery监控数据是否变化(修正版)

    jquery监控数据是否变化(修正版)

    jquery监控数据是否变化(修正版) 之前写的那篇中存在许多bug,今天重新整理了一下。还请各位指教
    2011-04-04
  • jQuery无刷新分页完整实例代码

    jQuery无刷新分页完整实例代码

    这篇文章主要介绍了jQuery无刷新分页实现方法,以完整实例形式分析了jQuery实现分页的数值计算与元素操作相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • 基于jQuery1.9版本如何判断浏览器版本类型

    基于jQuery1.9版本如何判断浏览器版本类型

    在jquery.1.9以前的版本,可以使用$.browser很轻松的判断浏览器的类型和版本,但是在1.9中和以后的版本中,$.browser已经被删除,下面就介绍一下如何实现此功能,希望能够给需要的朋友带来帮助
    2016-01-01
  • jquery中的mouseleave和mouseout的区别 模仿下拉框效果

    jquery中的mouseleave和mouseout的区别 模仿下拉框效果

    不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件,只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件
    2012-02-02
  • 基于jQuery实现的无刷新表格分页实例

    基于jQuery实现的无刷新表格分页实例

    这篇文章主要介绍了基于jQuery实现的无刷新表格分页方法,结合完整实例形式较为详细的分析了jQuery实现无刷新表格分页的具体步骤与相关实现代码,需要的朋友可以参考下
    2016-02-02
  • jquery html添加元素/删除元素操作实例详解

    jquery html添加元素/删除元素操作实例详解

    这篇文章主要介绍了jquery html添加元素/删除元素操作,结合实例形式详细分析了jquery html添加元素/删除元素相关函数功能、用法及操作注意事项,需要的朋友可以参考下
    2020-05-05
  • jQuery对html元素取值与赋值的方法

    jQuery对html元素取值与赋值的方法

    这篇文章主要介绍了jQuery对html元素取值与赋值的方法,有需要的朋友可以参考一下
    2013-11-11
  • JQuery 常用方法基础教程

    JQuery 常用方法基础教程

    对于学习使用jquery 的朋友,能用的到,简单的了解下jquery的一些操作。
    2009-02-02
  • jQuery Tree Multiselect使用详解

    jQuery Tree Multiselect使用详解

    这篇文章主要为大家详细介绍了jQuery Tree Multiselect的使用方法,这个插件允许用户以树型的形式来呈现列表复选框的选择,多用于权限管理中用于分配不同的权限,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05

最新评论