JavaScript模块化:使用requireJS按需加载

模块加载器的概念可能稍微接触过前端开发的童鞋都不会陌生,通过模块加载器可以有效的解决这些问题:

  1. JS文件的依赖关系。
  2. 通过异步加载优化script标签引起的阻塞问题
  3. 可以简单的以文件为单位将功能模块化并实现复用

主流的JS模块加载器有requireJSSeaJS等,加载器之间可能会因为遵循的规范不同有微妙的差别,从纯用户的角度出发,之所以选requireJS而不是SeaJS主要是因为:

  • 功能实现上两者相差无几,没有明显的性能差异或重大问题。
  • 文档丰富程度上,requireJS远远好于SeaJS,就拿最简单的加载jQuery和jQuery插件这回事,虽然两者的实现方法相差无几, 但requireJS就有可以直接拿来用的Demo,SeaJS还要读文档自己慢慢折腾。一些问题的解决上,requireJS为关键词也更容易找到答 案。
requireJS 加载jQuery + jQuery插件

可能对于一般Web App来说,引入jQuery及相关插件的概率是最大的,requireJS也亲切的给出了相应的解决方案及动态加载jQuery及插件的文档及实例代码

在最新的jQuery1.9.X中,jQuery已经在最后直接将自己注册为一个AMD模块,即是说可以直接被requireJS作为模块加载。如果是加载旧版的jQuery有两种方法:

1. 让jQuery先于requireJS加载

2. 对jQuery代码稍做一点处理,在jQuery代码包裹一句:

define(["jquery"], function($) {  
    // $ is guaranteed to be jQuery now */  
}); 



requireJS的示例中,直接将requireJS与jQuery合并为一个文件,如果是采用jQuery作为核心库的话推荐这种做法。

同样对于jQuery插件来说也有两种方法

1. 在插件外包裹代码

define(["jquery"], function($){  
     // Put here the plugin code.   
});



2. 在使用reuqireJS代码加载前注册插件(比如在main.js)中

requirejs.config({  
    "shim": {  
        "jquery-cookie"  : ["jquery"]  
    }  
});



requireJS加载第三方类库

在实例的App中还用到了jQuery以外的第三方类库,如果类库不是一个标准的AMD模块而又不想更改这些类库的代码,同样需要提前进行定义:

require.config({  
      paths: {  
            'underscore': 'vendor/underscore'  
      },  
      shim: {  
          underscore: {  
              exports: '_'  
          }  
      }  
});



CSS文件的模块化处理

在requireJS中,模块的概念仅限于JS文件,如果需要加载图片、JSON等非JS文件,requireJS实现了一系列加载插件

但是遗憾的是requireJS官方没有对CSS进行模块化处理,而我们在实际项目中却往往能遇到一些场景,比如一个轮播的图片展示栏,比如高级编辑器等等。几乎所有的富UI组件都会由JS与CSS两部分构成,而CSS之间也存在着模块的概念以及依赖关系。

为了更好的与requireJS整合,这里采用require-css来解决CSS的模块化与依赖问题。

require-css是一个requireJS插件,下载后将css.js与normalize.js放于main.js同级即可默认被加载,比如在我们的项目中需要加载jQuery Mobile的css文件,那么可以直接这样调用:

require(['jquery', 'css!../css/jquery.mobile-1.3.0.min.css'], function($) {  
});



不过由于这个CSS本质上是属于jQuery Mobile模块的一部分,更好的做法是将这个CSS文件的定义放在jQuery Mobile的依赖关系中,最终我们的requireJS定义部分为:

require.config({  
      paths: {  
            'jquerymobile': 'vendor/jquery.mobile-1.3.0',  
            'jstorage' : 'vendor/jstorage',  
            'underscore': 'vendor/underscore'  
      },  
      shim: {  
          jquerymobile : {  
            deps: [  
                'css!../css/jquery.mobile-1.3.0.min.css'  
            ]  
          },  
          underscore: {  
              exports: '_'  
          }  
      }  
});



在使用模块时,只需要:

require(['jquery', 'underscore', 'jquerymobile', 'jstorage'], function($, _) {  
});



jQuery Mobile的CSS文件就会被自动加载,这样CSS与JS就被整合为一个模块了。同理其他有复杂依赖关系的模块也可以做类似处理,requireJS会解决依赖关系的逻辑。

数据源的加载与等待

Web App一般都会动态加载后端的数据,数据格式一般可以是JSON、JSONP也可以直接是一个JS变量。这里以JS变量为例:

var restaurants = [  
    {  
        "name": "KFC"  
    },  
    {  
        "name": "7-11"  
    },  
    {  
        "name": "成都小吃"  
    }  
]



载入这段数据:

$.getScript('data/restaurants.json', function(e){  
    var data = window.restaurants;  
    alert(data[0].name); //KFC  
});



单一的数据源确实很简单,但是往往一个应用中会有多个数据源,比如在这个实例App中UI就需要载入用户信息、餐厅信息、订餐信息三种数据后才能工作。如果仅仅靠多层嵌套回调函数的话,可能代码的耦合就非常重了。

为了解决多个数据加载的问题,我习惯的解决方法是构造一个dataReady事件响应机制。

var foodOrder = {  
  
    //数据载入后要执行的函数暂存在这里  
    dataReadyFunc : []  
  
    //数据源URL及载入状态  
    , dataSource : [  
        { url : 'data/restaurants.json', ready : false, data : null },  
        { url : 'data/users.json', ready : false, data : null },  
        { url : 'data/foods.json', ready : false, data : null }  
    ]  
  
    //检查数据源是否全部载入完毕  
    , isReady : function(){  
        var isReady = true;  
        for(var key in this.dataSource){  
            if(this.dataSource[key].ready !== true){  
                isReady = false;  
            }  
        }  
        return isReady;  
    }  
  
    //数据源全部加载完毕,则逐一运行dataReadyFunc中存放的函数  
    , callReady : function(){  
        if(true === this.isReady()){  
            for(var key in this.dataReadyFunc){  
                this.dataReadyFunc[key]();  
            }  
        }  
    }  
  
    //供外部调用,会将外部输入的函数暂存在dataReadyFunc中  
    , dataReady : function(func){  
        if (typeof func !== 'function') {  
            return false;  
        }   
        this.dataReadyFunc.push(func);  
    }  
  
    , init : function(){  
        var self = this;  
        var _initElement = function(key, url){  
            $.getScript(url, function(e){  
                //每次载入数据后,将数据存放于dataSource中,将ready状态置为true,并调用callReady  
                self.dataSource[key].data = window[key];  
                self.dataSource[key].ready = true;  
                self.callReady();  
            });  
        }  
        for(var key in this.dataSource){  
            _initElement(key, this.dataSource[key].url);  
        }  
    }  
}



用法为:

foodOrder.dataReady(function(){  
   alert(1);       
});  
foodOrder.init();



dataReady内的alert将会在所有数据载入完毕后开始执行。

这段处理的逻辑并不复杂,将所有要执行的方法通过dataReady暂存起来,等待数据全部加载完毕后再执行,更加复杂的场景此方法仍然通用。

转载于:https://my.oschina.net/tongjh/blog/517989

步骤一:引入JS文件 在要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js 备注:支持使用 AMD/CMD 标准模块加载方法加载 步骤二:通过config接口注入权限验证配置 所有使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。 wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,企业号的唯一标识,此处填写企业号corpid timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsApiList: [] // 必填,使用JS接口列表,所有JS接口列表见附录2 }); 步骤三:通过ready接口处理成功验证 wx.ready(function(){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不要放在ready函数中。 }); 步骤四:通过error接口处理失败验证 wx.error(function(res){ // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 }); 接口调用说明 所有接口通过wx对象(也可使用jWeixin对象)来调用,参数是一个对象,除了每个接口本身要传的参数之外,还有以下通用参数: success:接口调用成功时执行的回调函数。 fail:接口调用失败时执行的回调函数。 complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。 cancel:用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。 trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值