JS的各种模块化方案使用方式(IIFE、AMD、CMD、COMMONJS、UMD)

目录

说明

IIFE(Immediately Invoked Function Expression)

AMD(Asynchronous Module Definition)

CMD(Common Module Definition)

CommonJS

UMD

ES6模块


说明

首先要说明的是,这些模块化的方案已经过时了,只有一些还需要维护的老项目的还在使用,当前基本都是用打包器打包的模块化方案,例如webpack,通过webpack打包之后的方案,就是webpack模块化方式。

IIFE(Immediately Invoked Function Expression)

这是一种原始的方式,能起到的作用仅仅只是隔离模块之间额命令冲突,将各种名字限制在模块内部。模块之间的依赖关系依靠程序员手动解决,通过在html中手动编写script标签来确定依赖关系。

模块定义:

//模块 moduleA.js
(function(window) {
    window.jQuery = {
       // 这里是代码 
    };
})(window);
//模块 moduleB.js
(function(window,jQuery) {
    window.my_module = {
       // 这里是代码 
        moduleBProerty:jQuery.xxxxx  //模块A中定义了全局模块jQuery,这里引用了jQuery,于是moduleB.js依赖moduleA.js
    };
})(window,window.jQuery);
//index.html

//moduleB.js依赖moduleA.js,所以先引入moduleA.js
<script src="moudleA.js"></script>
<script src="moudleB.js"></script>

AMD(Asynchronous Module Definition)

文档地址:RequireJS API

AMD规范的实现方式是RequireJS。

AMD (Asynchronous Module Definition)也是一种 JavaScript模块化规范。从名字上可以看出,它主要提供了异步加载的功能。这种方式更加自动化,不需要手动确定依赖关系,使用方式也及其简单。

假设具有如下目录结构的项目:

  • www/
    • index.html
    • js/
      • app/
        • sub.js
      • lib/
        • jquery.js
        • canvas.js
      • app.js
      • require.js

在index.html中:

<script data-main="js/app.js" src="js/require.js"></script>

在app.js中:

requirejs.config({
    //By default load any module IDs from js/lib
    baseUrl: 'js/lib',
    //except, if the module ID starts with "app",
    //load it from the js/app directory. paths
    //config is relative to the baseUrl, and
    //never includes a ".js" extension since
    //the paths config could be for a directory.
    paths: {
        app: '../app'
    }
});

// Start the main app logic.
requirejs(['jquery', 'canvas', 'app/sub'],
function   ($,        canvas,   sub) {
    //jQuery, canvas and the app/sub module are all
    //loaded and can be used here now.
});

对于requirejs.config()而言,其参数对象中最重要的两个值就是baseUrl与Paths了,baseUrl定义了这些模块的起始Url地址(如果没有通过requirejs.config配置baseUrl,那么就会取data-main的JS文件所在的目录作为baseUrl;如果没有配置baseUrl或者data-main,则baseUrl默认为index.html的目录路径。),Paths定义了这些模块的相对路径,这个相对路径是相对于baseUrl而言的。

上述引入方式只适合单入口的项目。

将config作为模块引入执行。

在index.html中引入:

<script src="scripts/require.js"></script>
<script>
//在这里,requirejs.config在scripts/config模块中被调用,然后当script/config模块执行完成之后,就会执行这里的回调,从而这里的require得到执行,相关模块被加载。
require(['scripts/config'], function() {
    // Configuration loaded now, safe to do other require calls
    // that depend on that config.
    require(['foo'], function(foo) {

    });
});
</script>

定义模块:

定义模块最好采用define(name,callback)与define(callback)这两种形式,而不要采用define(name,deps,callback)这种方式。

具体见:RequireJs运行原理 - axl234 - 博客园   末尾

但是在官方文档中,又建议不要给模块命令,所以就只剩下define(callback)这一种方式了。

目录结构:

* moduleA.js

* moduleB.js

* dir/

          * test.js

//文件名:test.js
define(function(require){
    //在内部引入依赖模块
    var moduleA=require("../moduleA");  //使用moduleA的相对路径即可。
    var moduleB=require("../moudleB");
    //这里开始写模块代码
    return {
        test: function(){
                 moduleA.test();
              }    
           }
});

CMD(Common Module Definition)

CMD(Common Module Definition)最初是由阿里的玉伯提出的,同AMD类似,使用CMD模块也需要使用对应的库SeaJS。SeaJS所要解决的问题和requireJS一样,但是在使用方式和加载时机上有所不同。

CMD的使用:

基本目录:

* CMD/

   * index.html

   * app.js

   * lib/

         * moduleA.js

         * moduleB.js

定义一个模块:

//定义moduleA模块 moduleA.js

//其中require用于载入其它模块,其中require.async用于懒加载。
//exports用于导出本模块的property
//module有三个properties,比较有用的就是module.exports。

//到处本模块接口的方式有两种弄:
//1. 通过exports一个接口一个接口的导出。exports.xxxxx = xxxxx
//2. 通过module.exports一次性全部到处。module.exports = { xxxxxxx  }

define(function(require,exports){
    exports.helloA=function(){
        console.log("This is moduleA.helloA!");
    }
});
//moduleB.js
define(function(require,module){
    var moduleA = require("./moduleA");
    moduleA.helloA();//调用moduleA中的hello()方法

    module.exports = {
        helloB:function(){
            console.log("This is moduleB!");
        }
    }

});

定义入口:

// app.js
define(function(require){
    var moduleB = require("./lib/moduleB");
    moduleB.helloB();
    console.log("This is app!");
})

定义html:

//index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  CMD
</body>
<script src="./static/sea.js"></script>
<script>
  seajs.config(
    {
      base:"./",
      alias:{
        moduleA:"lib/moduleA.js"
      }
    }
  );
  seajs.use("./app.js");
</script>
</html>

CommonJS

node原生支持CommonJS的模块化标准,因此在node中可以直接使用。

//moduleA.js

var add = function(a, b) {
    return a + b;
};
module.exports = {
    add: add
};

//main.js


var moduleA = require('./moduleA');
console.log(moduleA.add(1, 2));

UMD

UMD(Universal Module Define)其实就是一种兼容各大模块方式的写法。

// moduleA.js
(function(root, factory) {
    if (typeof module === 'object' && typeof module.exports === 'object') {
        console.log('是commonjs模块规范,nodejs环境')
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        console.log('是AMD模块规范,如require.js')
        define(function(require,exports,module){
              module.exports = factory();});
    } else if (typeof define === 'function' && define.cmd) {
        console.log('是CMD模块规范,如sea.js')
        define(function(require, exports, module) {
            module.exports = factory()
        })
    } else {
        console.log('没有模块环境,直接挂载在全局对象上')
        root.umdModule = factory(root);
    }
}(this, function() {
    return {
        helloA:function(){console.log("moduleA!")}
    }
}));

//main.js

(function(root, factory) {
    if (typeof module === 'object' && typeof module.exports === 'object') {
        console.log('是commonjs模块规范,nodejs环境')
        var depModule = require('./moduleA.js')
        module.exports = factory(depModule);
    } else if (typeof define === 'function' && define.amd) {
        console.log('是AMD模块规范,如require.js')
        define(function(require,exports,module){
              var depModule = require('./moduleA'); 
              module.exports = factory(depModule);});
    } else if (typeof define === 'function' && define.cmd) {
        console.log('是CMD模块规范,如sea.js')
        define(function(require, exports, module) {
            var depModule = require('./moduleA')
            module.exports = factory(depModule)
        })
    } else {
        console.log('没有模块环境,直接挂载在全局对象上')
        root.umdModule = factory(root.depModule);
    }
}(this, function(depModule) {
    console.log('我调用了依赖模块', depModule)
    depModule.helloA();
	// ...省略了一些代码,去代码仓库看吧
    return {
        name: '我自己是一个umd模块'
    }
}));

ES6模块

ES6的模块化_lengye7的博客-CSDN博客

这些例子,我放在Github上:IIFE AMD CMD CommonJS UMD都有。

GitHub - comefromezero/FrontModule: practice for IIFE AMD CMD UMD

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值