一、模块化概念
1、随着前端js代码复杂度的提高,JavaScript模块化概念便被提出来,前端社区也不断地实现前端模块化,直到es6对其进行了规范。
2、模块化的优点:
- 避免变量污染,命名冲突
- 提高代码的复用率
- 提高可维护性
- 方便管理依赖关系
3、为了避免缺少模块带来的问题,了解下程序员们的应对经历:
- 函数封装
- 对象封装
- 自执行函数表达式
- 模块化
4、前端模块化方案
- es6 module
- commonjs : nodejs使用的模块规范
- AMD : 代表 require.js
- CMD : 代表 sea.js
AMD 和 CMD ,两者的区别是前者对于以来的模块提前执行,而后者是延迟执行。前者推崇依赖前置,而后者推崇依赖就近,即只在需要用到某个模块的时候再require
二、AMD
AMD是RequireJS 在推广过程中对模块定义的规范化产出。
AMD规范是非同步加载模块,允许指定回调函数。
require.js 是一个在浏览器端实现模块化的方案
AMD官网:链接
导出:使用 define() 方法定义导出
// 定义当前的模块
define(function () {
// 模块化的环境
let msg = '我是m1模块';
function getMsg() {
return msg;
}
// 暴露出对应的函数和变量
return {
msg,
getMsg
}
})
// 模块2
define(function(){
function getM2(){
return '我是m2中的方法'
}
return {
getM2
}
})
// 模块3
// 参数1:指定要引入的模块
define(['mod2'], function (mod2) {
function getMsg() {
return '调用模块2中的方法:' + mod2.getM2()
}
return {
getMsg
}
})
模块化主入口分配文件
// 模块化的主入口分配文件
(function () {
// 关于requireJS加载模块的配置
requirejs.config({
// 配置js路径
paths: {
// 引入对应模块它的路径,不要写.js文件
m1: './m1',
mod2: './m2',
m3: './m3',
jq: './jquery'
}
});
// 后台语言中,命名空间
requirejs(['m1', 'm3', 'jq'], function (modu1, modu3) {
// 此环境就是你调用模块中方法的环境
console.log(modu1.getMsg());
console.log(modu3.getMsg());
$('h3').css({ color: 'red', fontSize: '30px' });
})
})()
引入: 我们在引入到html文件中时,只需要引入主入口 文件即可
<!-- requirejs是一个在浏览器端实现模块化的方案 -->
<script src="./lib/require.js" data-main="./js/index.js"></script>
三、CMD
CMD 是seaJS 在推广过程中对模块定义的规范化产出。
定义一个没有依赖的模块
//require 是导入
//exports 和 module 是导出
define(function (require, exports, module) {
function fn1() {
console.log("m1模块下面的fn1方法");
};
// 导出模块/暴露一个对象
module.exports = {
fn1
}
})
定义一个有依赖的模块
define(function (require, exports, module) {
// 导入依赖模块
let m1 = require('./m1')
m1.fn1()
function fn2() {
console.log('我是m2模块下面的fn2方法');
}
exports.fn2 = fn2
});
主入口文件
define(function (require) {
let m2 = require('./m2')
m2.fn2()
let jquery = require('./jquery')
console.log(jquery('body'));
})
在页面中引用
<script src="./lib/sea.js"></script>
<script>
seajs.use('./module/main.js')
</script>
四、commonJS
前端浏览器不支持,Nodejs中使用的是这个规范,核心思想就是通过require方法来同步加载所依赖的其他模块,然后通过 exports 或者 module.exports 来导出需要暴露的接口。
1、在官网下载安装包进行安装nodejs环境
下载地址: https://nodejs.org/zh-cn/download/
2、使用nvm安装nodejs
nvm可以非常方便的切换nodejs版本
window下载地址:https://github.com/coreybutler/nvm-windows
mac/linux下载地址:https://github.com/nvm-sh/nvm
3、检查nodejs是否安装成功
命令窗口(cmd)下面输入 node -v 指令出现版本号即安装成功
4、使用node执行js
使用 node 指令执行js文件
node xxx.js
必须在当前路径下执行该js文件
5、导出模块
语法: module.exports = 对象
// 类
/* class User {
say() {
console.log('你好世界');
}
}
const user = new User;
// 导出
module.exports = user;
*/
var msg = '111'
function say() {
console.log(1111);
}
function say2() {
console.log(22222);
}
module.exports = {
msg,
say,
say2
};
6、导入模块
语法:const 变量 = require(路径)
// 导入
// const user = require('./modules/user')
const { say: mySay, say2 } = require('./modules/user')
mySay()
五、es6 module
在ES6中,我们可以使用 import 关键字引入模块,通过 exprot 关键字导出模块,功能较之于前几个方案更为强大,也是我们所推崇的,但是由于ES6模块化目前还无法在所有的浏览器中支持,所以在浏览器中使用需要进行编译处理。目前chrome是支持的。
export [default] 对象
import * as obj form ‘路径’
import xxx form ‘路径’
import {xx as 别名} from ‘路径’
1、当前文件只有一个方法,可以使用默认导出
默认导出一个文件只能用一次
语法:export default 对象
function request(){
return "发送请求"
}
export default request
export default function request(){
return "发送请求"
}
默认导入
import myRequest from "./request.js"
2、命名导出
// 导出事先定义的特性
export { myFunction,myVariable };
// 导出单个特性(可以导出var,let,
//const,function,class)
export let myVariable = Math.sqrt(2);
export function myFunction() { ... };
命名导入
import {foo, bar} from '/modules/my-module.js';
3、命名导出可以和默认导出共存
export const aa = () => console.log(1111);
// 按需导出和默认导出可以共存
var obj = {
id: 1,
userFn
};
export default obj;
import myobj, {aa} from '/modules/my-module.js';