前端模块化详解

1.模块化的理解

模块有两个核心要素:隐藏和暴露
隐藏的,是自己的内部实现
暴露的,是希望外部使用的接口

在node.js中,由于只有一个入口文件,而开发一个应用肯定会涉及到多个文件的配合,因此,node.js对模块化的需求比浏览器端要大

2.模块化的规范

1.CommonJS

适用于服务器端的模块化,如果要用在浏览器端,需要借助browserify将app.js文件打包编译
CommonJS使用exports导出模块,require导入模块
nodejs中导入模块,使用相对路径,并且必须以./../开头
nodejs对CommonJS的实现
为了实现CommonJS规范,nodejs对模块做出了以下处理

  • 1.为了保证高效的函数运行,仅加载必要的模块。nodejs只有执行到require函数时才会加载并执行模块
  • 2.为了隐藏模块中不被导出的代码,nodejs执行模块时,会将模块中的所有代码放在一个函数中执行,以保证不污染全局变量
  • 3.为了保证顺利导出模块的内容,nodejs做了以下处理
    1)在模块开始执行前,初始化一个值module.exports = {}
    2)module.exports = {}即模块的导出值
    3)为了方便开发者便捷的导出,node在初始化完module.exports后,又声明了一个变量exports = module.exports
  • 4为了避免反复加载同一个模块,nodejs默认开启了模块缓存,如果加载的模块已经被加载过了,则会自动使用之前的导出结果
(function (module) {
  module.exports = {};
  var exports = module.exports;
  // 模块中的代码
  return module.exports;
})();

两种导出方式

方法一

一个文件中可以导出多个

exports.getNumber = getNumber;
exports.abc = 123;
var count = 0;
function getNumber() {
  count++;
  return count;
}
// exports = {}相当于一个对象
exports.getNumber = getNumber;

/**
 * exports={
 *  getNumber: getNumber
 * }
 */
方法二

一个文件中只能导出一个,相当于导出全部内容

 /** 定义模块 example.js **/
var x = 5;
var addX = function(value){
    return value + x;
}
module.exports.x = x;
module.exports.addX = addX;

总结:其实两者本质上没啥区别

导入
 //  app.js
/** 引用模块 **/
var example = require('./example')
console.log(example.x)
console.log(example.addX(1))

CommonJS的加载机制

2.AMD

是异步模块加载机制
require.js实现了AMD规范,使用时需要引用require.js
在浏览器端使用

<script data-main="./index.js" type="./require.js"></script>

index.js是入口文件

define([依赖的模块列表], function(模块名称列表) {
	 // 模块内部的代码
	return 导出的内容
})

在AMD中,导入和导出模块的代码,都必须放置在define函数中

导出

// a.js
define(function() {
// 模块内部的代码
	var a = 1;
	var b = 2;
	return {
		name: "a模块",
		data: "a模块的数据"
	}
})

导入

/**
define([依赖的模块列表], function(模块名称列表) {
	 // 模块内部的代码
	return 导出的内容
})
*/
define(["a"], function(a) {
	 // 模块内部的代码,等a.js加载完后再运行
	 console.log(a)
})

3.CMD

公共模块定义规范
sea.js实现了CMD规范

<script  type="./sea.js"></script>
<script>
	seajs.use("./index.js")
</script>

在CMD中,导入和导出模块的代码,都必须放在define函数中

define(function(require, exports, modules) {
	// 模块内部的代码
})

例子:

define(function(require, exports, modules) {
	var a = require("a")
	// 模块内部的代码
	module.exports = "a模块的内容"
})

4.ES6模块化

export命令用于规定模块的对外接口,import命令用于输入其他模块的功能
分为基本导出和默认导出

基本导出

export var a = 1

或者

/** 定义模块 math.js **/
var basicNum = 0;
var add = function (a, b) {
    return a + b;
};
export { basicNum, add };

默认导出

每个模块,除了允许有多个基本导出外,还允许有一个默认导出
默认导出类似于CommonJS中的module.exports,由于只有一个,因此无需具名

export default 默认导出的数据

导入

/** 引用模块 **/
import { basicNum, add } from './math';
function test(ele) {
    ele.textContent = add(99 + basicNum);
}

导入默认导出和基本导出

data是默认导出,a和b是基本导出

import data, {a, b} from "a.js"

总结

  • CommonJS规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。
  • AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。
  • CMD规范与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重
  • ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值