模块化
模块化进化史
1.全局 functon 模式
//module1.js
//数据
let data = 'atguigu.com'
//操作数据的函数
function foo() {
console.log(`foo() ${data}`)
}
<script type="text/javascript" src="module1.js"></script>
<script type="text/javascript">
//全局函数模式: 将不同的功能封装成不同的全局函数
//问题: Global 被污染了, 很容易引起命名冲突
let data = "修改后的数据"
foo()
</script>
2.namespace 模式
// module2.js
let myModule = {
data: 'atguigu.com',
foo() {
console.log(`foo() ${this.data}`)
}
}
<script type="text/javascript" src="module2.js"></script>
<script type="text/javascript">
//namespace模式: 简单对象封装
//作用: 减少了全局变量
//问题: 不安全
myModule.foo()
myModule.data = 'other data' //能直接修改模块内部的数据
myModule.foo()
</script>
3.IIFE 模式
//module3.js
(function (window) {
//数据
let data = 'atguigu.com'
//操作数据的函数
function foo() { //用于暴露函数
console.log(`foo() ${data}`)
}
//暴露行为
window.myModule = {foo}
})(window)
<script type="text/javascript" src="module3.js"></script>
<script type="text/javascript">
//IIFE模式: 匿名函数自调用(闭包)
//IIFE : immediately-invoked function expression(立即调用函数表达式)
//作用: 数据是私有的, 外部只能通过暴露的方法操作
//问题: 如果当前这个模块依赖另一个模块怎么办?
myModule.foo()
console.log(myModule.data) //undefined 不能访问模块内部数据
myModule.data = 'xxxx' //不是修改的模块内部的 data
myModule.foo() //没有改变
</script>
4.IIFE模式增强
//引入 jquery 到项目中
//module4.js
(function (window, $) {
//数据
let data = 'atguigu.com'
//操作数据的函数
function foo() { //用于暴露有函数
console.log(`foo() ${data}`)
$('body').css('background', 'red')
}
//暴露行为
window.myModule = {foo}
})(window, jQuery)
<script type="text/javascript" src="jquery-1.10.1.js"></script>
<script type="text/javascript" src="module4.js"></script>
<script type="text/javascript">
//IIFE 模式增强: 引入依赖
//这就是现代模块实现的基石
myModule.foo()
//一个页面需要引入多个js文件
//问题:
//请求过多
//依赖模糊
//难以维护
//这些问题可以通过现代模块化编码和项目构建来解决
</script>
commonjs
服务器 nodejs
客户端 browserify 也称为 commonjs 的浏览器端的打包工具
1.下载安装node.js
2.创建项目结构
|-modules
|-module1.js
|-module2.js
|-module3.js
|-app.js
|-package.json //npm init
{
"name": "commonJS-node",
"version": "1.0.0"
}
3.下载第三方模块 npm install uniq --save
4.模块化编码
//module1.js
module.exports = {
foo() {
console.log('moudle1 foo()')
}
}
//module2.js
module.exports = function () {
console.log('module2()')
}
//module3.js
exports.foo = function () {
console.log('module3 foo()')
}
exports.bar = function () {
console.log('module3 bar()')
}
// app.js
/**
1. 定义暴露模块:
module.exports = value;
exports.xxx = value;
2. 引入模块:
var module = require(模块名或模块路径);
*/
"use strict";
//引用模块
let module1 = require('./modules/module1')
let module2 = require('./modules/module2')
let module3 = require('./modules/module3')
let uniq = require('uniq')
let fs = require('fs')
//使用模块
module1.foo()
module2()
module3.foo()
module3.bar()
console.log(uniq([1, 3, 1, 4, 3]))
fs.readFile('app.js', function (error, data) {
console.log(data.toString())
})
5.通过 node 运行 app.js node app.js
ES6 (Babel-Browserify)
1. 定义 package.json 文件
{
"name" : "es6-babel-browserify",
"version" : "1.0.0"
}
2.安装 babel-cli, babel-preset-es2015 和 browserify
- npm install babel-cli browserify -g
- npm install babel-preset-es2015 --save-dev
3.定义 .babelrc 文件
{
"presets": ["es2015"]
}
4.编码
// js/src/module1.js
export function foo() {
console.log('module1 foo()');
}
export let bar = function () {
console.log('module1 bar()');
}
export const DATA_ARR = [1, 3, 5, 1]
// js/src/module2.js
let data = 'module2 data'
function fun1() {
console.log('module2 fun1() ' + data);
}
function fun2() {
console.log('module2 fun2() ' + data);
}
export { fun1, fun2 }
// js/src/module3.js
export default {
name: 'Tom',
setName: function (name) {
this.name = name
}
}
// js/src/app.js
import { foo, bar } from './module1'
import { DATA_ARR } from './module1'
import { fun1, fun2 } from './module2'
import person from './module3'
import $ from 'jquery'
$('body').css('background', 'red')
foo()
bar()
console.log(DATA_ARR);
fun1()
fun2()
person.setName('JACK')
console.log(person.name);
5.编译
- 使用 Babel 将 ES6 编译为 ES5 代码(但包含 CommonJS 语法) : babel js/src -d js/lib
- 使用 Browserify 编译 js : browserify js/lib/app.js -o js/lib/bundle.js
6.页面中引入测试
<script type="text/javascript" src="js/lib/bundle.js"></script>
7. 引入第三方模块(jQuery)
- 下载 jQuery 模块:
npm install jquery@1 --save
- 在 app.js 中引入并使用
js import $ from 'jquery' $('body').css('background', 'red')
AMD-RequireJS 模块化 (专用于浏览器端)
1.下载require.js, 并引入
- 官网: http://www.requirejs.cn/
- github : https://github.com/requirejs/requirejs
- 将 require.js 导入项目: js/libs/require.js
2.创建项目结构
|-js
|-libs
|-require.js
|-modules
|-alerter.js
|-dataService.js
|-main.js
|-index.html
3.定义 require.js 的模块代码
//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}
})
4.应用主(入口)js: main.js
(function () {
//配置
require.config({
//基本路径
baseUrl: "js/",
//模块标识名与模块路径映射
paths: {
"alerter": "modules/alerter",
"dataService": "modules/dataService",
}
})
//引入使用模块
require( ['alerter'], function(alerter) {
alerter.showMsg()
})
})()
5.页面使用模块:
<script data-main="js/main" src="js/libs/require.js"></script>
6.使用第三方基于 require.js 的框架(jquery)
-
将 jquery 的库文件导入到项目:
js/libs/jquery-1.10.1.js
-
在 main.js 中配置 jquery 路径
paths: { 'jquery': 'libs/jquery-1.10.1' }
-
在 alerter.js 中使用 jquery
define(['dataService', 'jquery'], function (dataService, $) { var name = 'xfzhang' function showMsg() { $('body').css({background : 'red'}) alert(name + ' '+dataService.getMsg()) } return {showMsg} })
7.使用第三方不基于 require.js 的框架(angular/angular-messages)
- 将 angular.js 和 angular-messages.js 导入项目
- js/libs/angular.js
- js/libs/angular-messages.js
- 在 main.js 中配置
(function () { require.config({ //基本路径 baseUrl: "js/", //模块标识名与模块路径映射 paths: { //第三方库 'jquery' : 'libs/jquery-1.10.1', 'angular' : 'libs/angular', 'angular-messages' : 'libs/angular-messages', //自定义模块 "alerter": "modules/alerter", "dataService": "modules/dataService" }, /* 配置不兼容AMD的模块 exports : 指定导出的模块名 deps : 指定所有依赖的模块的数组 */ shim: { 'angular' : { exports : 'angular' }, 'angular-messages' : { exports : 'angular-messages', deps : ['angular'] } } }) //引入使用模块 require( ['alerter', 'angular', 'angular-messages'], function(alerter, angular) { alerter.showMsg() angular.module('myApp', ['ngMessages']) angular.bootstrap(document,["myApp"]) }) })()
- 页面:
<form name="myForm"> 用户名: <input type="text" name="username" ng-model="username" ng-required="true"> <div style="color: red;" ng-show="myForm.username.$dirty&&myForm.username.$invalid">用户名是必须的</div> </form>
CMD-SeaJS 模块化 (专用于浏览器端)
1.下载 sea.js, 并引入
- 官网: http://seajs.org/
- github : https://github.com/seajs/seajs
- 将sea.js导入项目: js/libs/sea.js
2.创建项目结构
|-js
|-libs
|-sea.js
|-modules
|-module1.js
|-module2.js
|-module3.js
|-module4.js
|-main.js
|-index.html
3.定义 sea.js 的模块代码
//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) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
4.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>
UMD(AMD和Commonjs的糅合)
UMD 先判断是否支持 Node.js 的模块(exports)是否存在,存在则使用 Node.js 模块模式。再判断是否支持 AMD(define 是否存在),存在则使用 AMD 方式加载模块。
(function (window, factory) {
if (typeof exports === 'object') {
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
define(factory);
} else {
window.eventUtil = factory();
}
})(this, function () {
//module ...
});
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具