js模块化学习笔记二:模块化规范

常见的模块化规范有:CommonJS、AMD、CMD、ES6

一、CommonJS

1).实现

服务器端:Node.js
浏览器端:Browserify

2)基本语法

定义暴露模块:exports
exports.xxx = value;
module.exports = value;
引入模块:require
var module = require(‘模块名/模块相对路径’)

3)引入模块发生什么时候?

Node:运行时,动态同步引入;
Browserify:在运行前对模块化进行编译打包的处理(已经将依赖的模块包含进来了),运行的是打包生成的js(浏览器不认识require),运行时不存在需要再从远程引入依赖模块。

4)代码实现

目录结构:
-modules
--module1.js
--module2.js
--module3.js
-node_modules
-app.js
-package.json

module1.js

//module.exports = value 暴露一个对象
module.exports = {
    msg : 'module1',
    foo(){
        console.log(this.msg);
    }
}

module2.js

//暴露一个函数 module.exports = function(){}
module.exports = function(){
    console.log('module2');
}
//不能无限添加,后面的代码会覆盖前面的代码

module3.js

//exports.xxx = value
//可以无限添加
exports.foo = function(){
    console.log("foo() module3");
};
exports.bar = function(){
    console.log("bar() module3");
}
exports.arr = [2,3,2,4,5,8,7,1];

app.js

//将其他模块汇集到主模块中
1. 定义暴露模块:
    module.exports = value;
    exports.xxx = value;
  2. 引入模块:
    var module = require(模块名或模块路径);
//第三方库要放在最上方
let uniq = require('uniq');
let module1 = require('./modules/module1');
let module2 = require('./modules/module2');
let module3 = require('./modules/module3');
module1.foo();
module2();
module3.foo();
module3.bar();
let result = uniq(module3.arr);
console.log(result);

package.json

{
  "name": "commonjs_node",
  "version": "1.0.0",
  "dependencies": {
    "uniq": "^1.0.1"
  }
}
浏览器端:CommonJS-Browserify

Index.html

<script type="text/javascript" src="js/src/app.js"></script>

浏览器不识别require,所以需要将js打包

二、AMD

1)实现

浏览器端:require.js(requireJS)

2)基本语法

定义暴露模块:

define([依赖模块名],function(){
    return 模块
})

引入模块:

require([‘模块1’,’模块2’],function(m1,m2){
//使用m1与m2
})

配置

require.config({
    //基本路径
baseUrl:’src/’,
//映射:模块标识名:路径
paths:{
    //自定义模块
    ‘a’:’modules/a’,
    ‘b’:’modules/b’,
    //第三方库
    ‘jquery’:’libs/jquery-1.10.1’
}
})
3)代码实现

dataService.js

//无依赖
define(function(){
    let msg = "atguigu.com"
    function getMsg(){
        return msg.toUpperCase();
    }
    return {getMsg}
})

Alerter.js

//有依赖
define([
    'dataService',
    'jquery'
], function(dataService, \$) {
   let name = "Tom2";
   function showMsg(){
       $('body').css('background','gray');
       alert(dataService.getMsg()+","+name);
   }
    return {showMsg}
});

Main.js

(function(){
    //配置
    require.config({
        //基本路径
        baseUrl : "js/",
        //模块标识与模块路径映射
        paths:{
            //第三方库
            "jquery":"libs/jquery-1.10.1",
            //自定义模块
            "alerter":"modules/alerter",
            "dataService":"modules/dataService"
        }
    })
    //引入使用模块
    require(['alerter'],function(alerter){
        alerter.showMsg()
    })
})()

Test.html

<script type="text/javascript" src="js/libs/require.js" data-main="js/main.js"></script>

data-main属性的作用是,指定网页程序的主模块。在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。

三、CMD

1)实现

浏览器端:sea.js(seaJS)

2)基本语法

定义暴露模块:

define(function(require,module,exports){
    通过require()引入依赖模块
    通过module/exports来暴露模块
    exports.xxx = value
})

使用模块:

seajs.user([‘模块1’],[‘模块2’])
3)代码实现

Module1.js

define(function(require,exports,module){
    //内部变量数据
    var data = "atguigu.com";

    function show(){
        console.log('module1 show()'+data);
    }

    //向外暴露
    exports.show = show;
});

Module2.js

define(function(require,exports,module){
    module.exports = {
        msg : 'I WILL BACK'
    }
})

Module3.js

define(function(require,exports,module){
    const API_KEY = "abc123";
    exports.API_KEY = API_KEY;
});

Module4.js

define(function(require,exports,module){
    //引入依赖模块(同步)
    var module2 = require('./module2');
    function show(){
       console.log("module4 show() "+module2.msg)
    }
    exports.show = show;

    //引入依赖模块(异步)
    require.async('./module3',function(m3){
        console.log('异步引入依赖模块3'+m3.API_KEY);
    })
});

Main.js

define(function(require){
    //不需要暴露时,形参只需要require即可
    var m1 = require('./module1');
    var m4 = require('./module4');
    m1.show();
    m4.show();
})

Index.html

<!--
使用seajs:
1.引入sea.js库
2.如何定义导出模块:
    define() exports module.exports
3.如何依赖模块:require()
4.如何使用模块:seajs.use()
-->
<script type='text/javascript' src="js/libs/sea.js"></script>
<script type='text/javascript'>
    seajs.use('./js/modules/main');
</script>

四、ES6

1)ES6内置了模块化的实现
2)基本语法

定义暴露模块:export
默认暴露(暴露一个数据):export default 对象
一般暴露(暴露多个数据):export {对象,对象}
引入使用模块 import
- 引入default 模块
import xxx from ‘模块路径/模块名’
- 引入一般模块:
import {a,b} from ‘模块路径/模块名’
import * as module1 from ‘模块路径/模块名’

3)问题

所有浏览器还不能直接识别ES6模块化的语法

4)解决

使用webpack编译打包

5)代码实现

.babelrc

{
    "presets":["es2015"]
}

module1.js

//暴露模块 分别暴露
export function foo(){
    console.log('foo() module1');
}

export function bar(){
    console.log('bar() module1');
}

module2.js

//统一暴露
function fun(){
    console.log('fun() module2');
}

function fun2(){
    console.log('fun2() module2');
}
export {fun,fun2};

module3.js

//默认暴露 可以暴露0,或者任意数据类型,
//暴露什么数据接收到的就是什么数据
//export default value;

export default () => {
    console.log('我是默认暴露的箭头函数');
}

Main.js

//引入其他的模块
//语法:import xxx from '路径'
import $ from 'jquery'
import {foo,bar} from './module1';
import {fun,fun2} from './module2';
import module3 from './module3';

$('body').css('background','red');
foo();
bar();
fun();
fun2();
module3();

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ES6</title>
</head>
<body>
    <!--<script type='text/javascript' src='js/src/main.js'></script>-->
    <script type='text/javascript' src='js/lib/bundle.js'></script>
</body>
</html>
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容