随着前端应用日趋复杂,项目代码也大量膨胀,模块化就是一种最主流的代码组织方式,一个模块就是一个实现特定功能的文件,它通过把我们的复杂代码按照功能的不同,划分为不同的模块单独维护的这种方式,去提高我们的开发效率,降低维护成本。要用什么功能就加载什么模块模块化开发是当下最重要的前端开发范式之一,其只是思想,不包含具体实现。
html文件:
<script type='text/javascript' src='module1.js'></script>
<script type='text/javascript'>
foo();
bar();
msg='NBA'; //会污染全局变量
foo();
</script>
js文件:
/**
* 全局函数模式: 将不同的功能封装成不同的全局函数
* 问题: Global被污染了, 很容易引起命名冲突
*/
let msg = 'modulel'
function foo() {
console.log('foo()', msg);
}
function bar() {
console.log('bar()', msg);
}
html文件:
<script type='text/javascript' src='module1.js'></script>
<script type='text/javascript'>
obj.foo();
obj.msg = 'NBA';
obj.foo();
</script>
js文件:
/**
* namespace模式: 简单对象封装
* 作用: 减少了全局变量
* 问题: 不安全(数据不是私有的, 外部可以直接修改)
*/
let obj = {
msg: 'atguigu',
foo() {
console.log('foo()', this.msg);
}
};
html文件:
<script type='text/javascript' src='module3.js'></script>
<script type='text/javascript'>
msg='NBA';
console.log(msg);//此时不会修改函数内部msg,相当于给window添加了msg属性
obj.foo(); //此时obj是window的一个对象,可以调用foo属性
</script>
js文件:
/**
* IIFE模式: 匿名函数自调用(闭包)
* IIFE : immediately-invoked function expression(立即调用函数表达式)
* 作用: 数据是私有的, 外部只能通过暴露的方法操作
* 问题: 如果当前这个模块依赖另一个模块怎么办?
*/
//IIFE模式
(function (window) {
let msg = 'atguigu';
function foo() {
console.log('foo()', msg);
}
window.obj = { foo } //向window暴露一个对象
})(window)
html文件:
<script type='text/javascript' src='jquery-1.10.1.js'></script>
<script type='text/javascript' src='module4.js'></script>
<script type='text/javascript'>
fn();
</script>
js文件:
/**
* IIFE模式增强 : 引入依赖
* 这就是现代模块实现的基石
*/
(function(window,$){
let msg='atguigu';
function foo() {
console.log('foo()',msg);
}
window.fn=foo; //向window添加方法
$('body').css('background','red'); //改变body的颜色
})(window,jQuery);
module.exports = value或exports.xxx = value
require(xxx)
第三方模块:xxx为模块名
自定义模块: xxx为模块文件路径
|-modules
|-module1.js
|-module2.js
|-module3.js
|-app.js
|-package.json
{
"name": "commonJS-node",
"version": "1.0.0"
}
注意:在创建package.json的时候可以手动创建,也可以npm init进行创建,但是根目录中不能出现中文字符
npm install uniq --save
## module1.js
// module.exports=value 暴露一个对象
module.exports={
msg:'module',
foo(){
console.log(this.msg);
}
}
## module2.js
/* 暴露一个函数 module.exports=function(){} */
module.exports=function(){
console.log('module2');
}
// module.exports=function(){} 会覆盖上一个函数
## module3.js
// exports.xxx = value
exports.foo = function () {
console.log('foo() module3');
}
exports.bar = function () {
console.log('bar() module3');
}
exports.arr=[2,4,5,2,3,5,1,11];
## app.js
// 将其他模块汇集到主模块
const uniq = require('uniq'); //第三方模块:xxx为模块名
let module1=require('./modules/module1'); //自定义模块: xxx为模块文件路径
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);
- 命令: node app.js
- 工具: 右键-->运行
|-js
|-dist //打包生成文件的目录
|-src //源码所在的目录
|-module1.js
|-module2.js
|-module3.js
|-app.js //应用主源文件
|-index.html
|-package.json
{
"name": "browserify-test",
"version": "1.0.0"
}
* 全局: npm install browserify -g
* 局部: npm install browserify --save-dev
注意:在下载browserify时,我只局部安装报错了,我全局安装以后就好使了。
## 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
//引用模块
let module1 = require('./module1')
let module2 = require('./module2')
let module3 = require('./module3')
let uniq = require('uniq')
//使用模块
module1.foo()
module2()
module3.foo()
module3.bar()
console.log(uniq([1, 3, 1, 4, 3]))
browserify js/src/app.js -o js/dist/bundle.js
其中:
-o:output
-js/src/app.js 是需要打包的文件路径
-js/dist/bundle.js 打包之后的输出路径
<script type="text/javascript" src="js/dist/bundle.js"></script>
引入的是打包好的文件,不要引错
定义没有依赖的模块:
define(function(){
.....
return 模块
})
定义有依赖的模块:
define(['module1','module2'],function(m1,m2){
.....
return 模块
})
引入模块:
require(['module1','module2'],function(m1,m2){
使用m1/m2
})
-----a:非AMD实现
|-js
|-src //源码所在的目录
|-alerter.js
|-dataService.js
|-index.html
|-app.js
## dataService.js
// 定义一个没有依赖的模块
(function(window){
let name='dataService.js';
function getName(){
return name
}
window.dataService={getName};
})(window)
## alerter.js
// 定义一个有依赖的模块
(function(window,dataService){
let msg='alerter.js'
function showMsg(){
console.log(msg,dataService.getName());
}
window.alerter={showMsg};
})(window,dataService)
## app.js
(function (alerter) {
alerter.showMsg();
})(alerter)
## test.html
<script src="./js/dataService.js"></script> //由于alerter.js依赖于dataService,所以也要在引入alerter之前引入dataService.js文件
<script src="./js/alerter.js"></script> //引入alerter.js文件
<script src="./app.js"></script> //单独引入app.js找不到alerter文件
-----b:AMD实现
|-js
|-libs
|-require.js
|-modules
|-alerter.js
|-dataService.js
|-main.js
|-index.html
##dataService.js
// 定义没有依赖的模块
define(function () {
let msg = 'atguigu.com'
function getMsg() {
return msg
}
// 暴露模块
return { getMsg }
})
##alerter.js
// 定义有依赖模块
define(['dataService'], function (dataService) {
let name = 'Tom2'
function showMsg() {
console.log(name, dataService.getMsg());
}
// 暴露模块
return { showMsg }
})
##main.js
// 引入模块
(function () {
// 配置
require.config({
//映射: 模块标识名: 路径
paths: {
//自定义模块
alerter: './modules/alerter',
dataService: './modules/dataService',
},
})
// 引入模块使用
requirejs(['alerter'], function (alerter) {
alerter.showMsg();
})
})()
##index.html
<script data-main="js/main.js" src="js/libs/require.js"></script>
##先加载require.js文件,然后加载main.js
- 将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}
})
专门用于浏览器端, 模块的加载是异步的 ;模块使用时才会加载执行。
define(function(require, exports, module){
exports.xxx = value
module.exports = value
})
define(function(require, exports, module){
//引入依赖模块(同步)
var module2 = require('./module2')
//引入依赖模块(异步)
require.async('./module3', function (m3) {
})
//暴露模块
exports.xxx = value
})
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
|-js
|-libs
|-sea.js
|-modules
|-module1.js
|-module2.js
|-module3.js
|-module4.js
|-main.js
|-index.html
##module1.js
// 定义没有依赖的模块
define(function (require, exports, module) {
let msg = 'module1';
function foo() {
return msg;
}
// 暴露模块
module.exports = { foo }
})
##module2.js
define(function (require, exports, module) {
let msg = 'module2';
function bar() {
console.log(msg);
}
// 暴露模块
module.exports = bar;
})
##module3.js
define(function (require, exports, module) {
let data = 'module3';
function fun() {
console.log(data);
}
// 暴露模块
exports.module3 = { fun };
})
##module4.js
define(function (require, exports, module) {
let msg = 'module4';
// 同步引入依赖模块
let module2 = require('./module2');
module2();
// 异步引入依赖模块
require.async('./module3', function (module3) {
module3.module3.fun();
});
function fun2() {
console.log(msg);
}
exports.fun2=fun2
})
##main.js
define(function(require){
let module1=require('./module1');
console.log(module1.foo());
let module4=require('./module4');
module4.fun2()
})
##index.html
<script type='text/javascript' src='js/libs/sea.js'></script>
<script type='text/javascript'>
seajs.use('./js/modules/main.js');
</script>
-1. 定义package.json文件
{
"name" : "es6-babel-browserify",
"version" : "1.0.0"
}
* 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('foo() module1');
}
export function bar(){
console.log('bar() module1');
}
export let arr=[1,2,3,4,5]
## js/src/module2.js
// 统一暴露
function fun() {
console.log('fun() module2');
}
function fun2() {
console.log('fun2() module2');
}
export { fun, fun2 };
## js/src/module3.js
//默认暴露 可以暴露任意数据类型,暴露什么数据类型,暴露什么数据接收到的就是什么数据
// export default value
// 方式一:
/* export default ()=>{
console.log('我是默认暴露的箭头函数');
} */
// 方式二:
export default {
msg: '默认暴露',
foo() {
console.log(this.msg);
}
}
## js/src/app.js
//引入其他的模块 语法:import xxx from '路径'
/* import module1 from './module1'
import module2 from './module2'
console.log(module1,module2); //undefined undefined
*/
// 引入第三方库
import $ from 'jquery'
// 需要使用解构赋值
import { foo, bar } from './module1'
import { fun, fun2 } from './module2'
import module3 from './module3'
$('body').css('background','green');
foo();
bar();
fun();
fun2();
// module3(); //默认暴露方式一的调用
module3.foo(); //默认暴露方式二的调用
* 使用Babel将ES6编译为ES5代码(但包含CommonJS语法) : babel js/src -d js/lib
* 使用Browserify编译js : browserify js/lib/app.js -o js/lib/bundle.js
<script type="text/javascript" src="js/lib/bundle.js"></script>
注意:引入的是经过打包处理之后的文件,并且如果有改动还需要重新编译打包。
1)下载jQuery模块:
npm install jquery@1 --save
2). 在app.js中引入并使用
import $ from 'jquery'
$('body').css('background', 'red')