zoukankan      html  css  js  c++  java
  • 【动态】简单的JS动态加载单体

    动态加载外部JS关于执行顺序,其实还存在问题! //2011-07-28

    -----------------------------------------------------

    原文来之:博客园idche

    前几天公司的项目需要这个功能,本来想找一个别人写的(别人的应该经过了许多测试,没啥问题)。

    由于对这个功能的要求不高,只需要简单动态加在加载,不重复加载,简单的依赖就可以了。

    最终还是自己花时间写了。

    如果你熟悉YUI,

    那么它跟YUI的工作方式很像

    添加一个JS

    WW.add('jQuery', 'http://code.jquery.com/jquery-1.6.1.min.js');

    使用一个JS

     

    WW.use('jQuery', function(){
    document.getElementById(
    'log').innerHTML += '<div>jQuery ok</div>';
    });


    还有关于script标签的加载完成事件

    /*
    var script = document.createElement('script');
    IE6 IE7 IE8 IE9 Chrome Firefox Opera
    script.onreadystatechange null null -- null undefined undefined undefined
    script.onload undefined undefined -- null null undefined null
    */

    一般返回null 说明是当前浏览器支持的事件(firefox除外,firfox其实支持的是 onload)。

    最重大的发现

    当你直接在页面写SCRIPT标签,与动态创建的SCRIPT标签,Opera 浏览器的事件支持是不一样的。

    直接创建:事件仅仅只有 onload

    动态创建:加在完成事件有 onreadystatechange  onload

    最终采用了 司徒正美 的方案(感谢,最后我觉得使用“document.dispatchEvent”还是有一定道理)。

    support:document.dispatchEvent ? 'onload' : 'onreadystatechange',

    源码(大约100行):

    View Code
    /*动态JS加载*/
    /*
    var script = document.createElement('script');
    IE6 IE7 IE8 IE9 Chrome Firefox Opera
    script.onreadystatechange null null -- null undefined undefined undefined
    script.onload undefined undefined -- null null undefined null
    */
    /*
    全局命名空间WW
    主要方法
    WW = {
    add:fucntion(namespace, url){}
    use:fucntion(namespaces, callback){}
    }

    方法 add(namespace, url, isOkay)
    说明 注册一个JS模块
    参数 namespace String
    参数 url String
    参数 isOkay Boolean 是否已经加载成功 可选 这个主要用于测试环境下很多文件,上线以合并成一个文件后注册空间不够

    方法 use(namespaces, callback);
    参数 namespaces String 可以是多个 namespace 使用逗号分割
    参数 callback Function JS全部加载完成回调方法

    */
    var WW = {
    support:document.dispatchEvent
    ? 'onload' : 'onreadystatechange',
    query:{
    /*队列*/},
    module:{
    /*成功注册的模块*/},
    add:
    function(namespace, url, isOkay){//注册一个命名空间
    var module = this.module;

    if(module[namespace]){
    throw namespace+ " is being";
    }

    module[namespace]
    = {};
    module[namespace].url
    = url;
    module[namespace].isOkay
    = isOkay || false;
    },
    use:
    function(namespaces, callback){//使用一个命名空间

    var task = {};
    var key;

    task.namespaces
    = namespaces.split(',');
    task.callback
    = callback || function(){};
    task.complet
    = 0;//已完成
    task.total = task.namespaces.length;//总量
    key = task.namespaces.join('');// 任务的KAY;

    this.query[ key ] = task;
    this.start(task, key );

    },
    start:
    function(task, key){//内部 开始加载一个任务

    var i = 0;
    var len = task.namespaces.length;
    var model;
    var modelKey;

    for(i; i<len; i++){
    modelKey
    = task.namespaces[i].replace(/^\s+|\s+$/g,'');
    model
    = this.module[ modelKey ];

    if(model === undefined){
    throw modelKey+' is undefined';
    }

    if(model.isOkay === false){
    model.isOkay
    = 1;
    this.load(model.url, modelKey, key);
    }
    else if(model.isOkay === true){
    this.checkBack(modelKey, key);
    }
    else{
    this.wait(model, modelKey, key);
    }
    }

    },
    wait:
    function(model, modelKey, key){// 处理,后一个任务包含前一个正在进行中的任务,而导致的重复加载问题
    var _this = this;
    var a = setInterval(function(){
    if(model.isOkay === true){
    clearInterval(a);
    _this.checkBack(modelKey, key);
    }
    },
    500);
    },
    checkBack:
    function(modelKey, key){//内部
    this.module[modelKey].isOkay = true;
    var query = this.query[key];
    if(++(query.complet) === query.total){
    query.callback();
    //回调函数
    delete this.query[key];
    }
    },
    load:
    function(url, modelKey, key){//内部 加载一个JS
    var _this = this;
    var script = document.createElement('script');

    script[
    this.support] = function(){
    if ( /undefined|loaded|complete/.test(script.readyState) ){
    _this.checkBack(modelKey, key);
    }
    };
    script.setAttribute(
    'type', 'text/javascript');
    script.setAttribute(
    'src', url);
    document.getElementsByTagName(
    'head')[0].appendChild(script);
    }
    };

    测试例子

  • 相关阅读:
    Entity Framework简介
    Java学习笔记-spring-Bean作用于
    Java学习笔记-spring-Bean实例化
    第四章--第二节:类
    为什么越来越少的人用jQuery
    年入50万的方法
    第一节--项目介绍和初始化
    第四章--第一节:函数
    第一节--API爬虫--环境设置与课程简介
    第三章--第六节:元祖
  • 原文地址:https://www.cnblogs.com/idche/p/2085018.html
Copyright © 2011-2022 走看看