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暂存起来,等待数据全部加载完毕后再执行,更加复杂的场景此方法仍然通用。

时间: 2024-10-11 13:18:31

JavaScript模块化:使用requireJS按需加载的相关文章

webpack css模块化和ant-design按需加载冲突

其实具体出现了什么问题,我也记得不清楚了,今天突然回想起来必须记录一下,一个思想就是用exclude将node_module目录下的文件排除,网上有很多相关例子,但不知是不是因为时间久远,都不生效,无奈,又只好啃回官方文档,我的解决方式如下 webpack正常打包的话,所有的css都会被打包在一起,造成css的全局污染,我们可以采用模块化的方式,其实就是借用hash改变类或id名 webpack.config.js module: { rules: [ { test: /\.(js|jsx)$/

angualrjs+AMD规范示例(主要使用requirejs)-实现按需加载

1.背景说明 最近一段时间,一直在研究angularjs及AMD.common规范等.但怎么把angularjs有效的与AMD模块组织结合在一起使用,还是值得深思. 本人研究一段时间,为了巩固下研究成果,特意写了一个demo,仅供参考. 2.使用技术点说明       kendo:主要使用kendo开源一些组件(由于本人对kendo研究比较多) angular:angular作为基础框架(MVC.DI.数据绑定.页面路由.相关服务等) requireJS:AMD模块加载器 bootstrap:主

Javascript模块化工具requirejs教程

转自:http://www.w3cschool.cc/w3cnote/requirejs-tutorial-1.html, http://www.w3cschool.cc/w3cnote/requirejs-tutorial-2.html 随着网站功能逐渐丰富,网页中的js也变得越来越复杂和臃肿,原有通过script标签来导入一个个的js文件这种方式已经不能满足现在互联网开发模式,我们需要团队协作.模块复用.单元测试等等一系列复杂的需求. RequireJS是一个非常小巧的JavaScript模

前端性能优化之按需加载(React-router+webpack)

一.什么是按需加载 和异步加载script的目的一样(异步加载script的方法),按需加载/代码切割也可以解决首屏加载的速度. 什么时候需要按需加载 如果是大文件,使用按需加载就十分合适.比如一个近1M的全国城市省市县的json文件,在我首屏加载的时候并不需要引入,而是当用户点击选项的时候才加载.如果不点击,则不会加载.就可以缩短首屏http请求的数量以及时间. 如果是小文件,可以不必太在意按需加载.过多的http请求会导致性能问题. 二.实现按需加载的方法 Webpack打包模块工具实现 R

webpack 代码拆分,按需加载

转自:https://segmentfault.com/a/1190000007649417?utm_source=weekly&utm_medium=email&utm_campaign=email_weekly 如果利用 webpack 将项目中的所有代码打包在一起,很多时候是不适用的,因为代码中有些东西我们总是希望将其拆分出来.比如: 样式表,希望利用 link 标签引入 使用概率较低的模块,希望后期需要的时候异步加载 框架代码,希望能利用浏览器缓存下部分不易变动的代码 下面是我在阅

按需加载.js .css文件

首先,理解按需加载当你需要用到某个js里面的函数什么鬼,或者某个css里的样式的时候你才开始加载这个文件. 然后是怎样实现的,简单来说就是在js中动态的createElem<script><link>这两种元算--这句话是说给自己的.可以绑定点击事件,滚轮事件(例如图片的懒加载是动态的.) 使用 require.js (一个按需加载的插件)管理.js按需加载,来自http://www.cnblogs.com/chenxizhang/archive/2013/05/16/308194

利用CSS、JavaScript及Ajax实现图片预加载的三大方法

原文:3 Ways to Preload Images with CSS, JavaScript, or Ajax 译文:利用CSS.JavaScript及Ajax实现图片预加载的三大方法 预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验.本文将分享三个不同的预加载技术,来增强网站的性能与可用性.

利用CSS、JavaScript及Ajax实现图片预加载的三大方法及优缺点分析

预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验.本文将分享三个不同的预加载技术,来增强网站的性能与可用性. 方法一:用CSS和JavaScript实现预加载 实现预加载图片有很多方法,包括使用CSS.JavaScript及两者的各种组合.这些技术可根据不同设计场景设计出相应的解决方案,十分高效.

图片按需加载实现

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>按需加载图片</title> 6 <style type="text/css"> 7 * { 8 margin: 0; 9 padding: 0; 10 } 11 ul{ 12 } 13 img{ 14 w