1. 模块化的理解
## 1). 什么是模块?
将一个js文件按照功能拆分成多个js文件,在通过某种语法将多个js文件汇总在一起就是模块化,
每一个js文件中的js代码都是独立运行在一个函数中,所以一个模块的中的变量和函数在其他模块中无法访问
2) 模块化优点
1、避免命名冲突(减少命名空间污染)
2、更好的分离, 按需加载
3、更高复用性
4、高可维护性
3)模块化缺点
1、页面引入加载script,请求过多
2、依赖模糊
2. 模块化在服务器端运行(CommonJS_Node模块化教程) 常用,一般用于nodejs
!! 1.引入其他的模块:(核心模块和自定义模块同时引入,核心模块放在前面,可以省略.js后缀名)
require()可以传递一个文件的路径作为参数,该函数会返回module.exports(默认情况下是个空对象)
对于核心模块(npm中下载的模块或nodejs核心模块),直接使用模块的名字对其进行引入
var fs = require("fs");
var express = require("express");
对于自定义的文件模块,需要通过文件的路径来对模块进行引入,路径可以是绝对路径,如果是相对路径必须以./或 ../开头
var router = require("./router");
!! 2.定义暴露模块(导出变量和函数):module.exports和exports是引用关系,module.exports={}/exports=module.exports
- 使用 exports
- 例子:
exports.属性 = 属性值;
exports.方法 = 函数;
- 使用module.exports 常用
- 例子:
module.exports.属性 = 属性值;
module.exports.方法 = 函数;
module.exports = {};
exports 和 module.exports的区别:
- 通过exports只能使用.的方式来向外暴露内部变量
- 而module.exports既可以通过.的形式,也可以直接赋值
3. 函数参数:
实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递进了5个实参
exports
- 暴露模块
require
- 引入模块
module
- module.exports暴露模块
__filename
C:\Users\lilichao\WebstormProjects\class0705\01.node\04.module.js
- 当前文件的绝对路径
__dirname
C:\Users\lilichao\WebstormProjects\class0705\01.node
- 当前文件所在文件夹的绝对路径
1) 创建项目结构
|-modules
|-module1.js
|-module2.js
|-module3.js
|-app.js
|-package.json
{
"name": "commonJS-node",
"version": "1.0.0"
}
2) 下载第三方模块(可选择)
* npm install uniq --save
3) 模块化编码module1.js、module2.js、module3.js
app.js (模块引入在主js上)
3. 模块化在浏览器端运行(CommonJS-Browserify模块化教程) 常用
1) 创建项目结构
|-js
|-dist //打包生成文件的目录
|-src //源码所在的目录
|-module1.js
|-module2.js
|-module3.js
|-app.js //应用主源文件
|-index.html
|-package.json
{
"name": "browserify-test",
"version": "1.0.0"
}
```
!! 2) 下载browserify(两步)
* 全局: npm install browserify -g
* 局部: npm install browserify --save-dev
3) 定义模块代码module1.js、module2.js、module3.js,
app.js (模块引入在主js上)
!! 4)cmd窗口编译处理app.js:(因为浏览器不认识require所以要编译)
* browserify js/src/app.js -o js/dist/bundle.js
原来的JS文件 解析后的js文件
5)页面使用引入:
<script type="text/javascript" src="js/dist/bundle.js"></script>
4.模块化在浏览器端运行(ES6-Babel-Browserify使用教程), 比较常用
//分别暴露
export function foo() {}
export let bar = function () {}
//统一暴露
export {fun1, fun2}
//默认暴露,只能暴露一次
export default {
name: 'Tom',
setName: function (name) {
this.name = name
}
}
//引入模块
import $ from 'jquery' 针对第三方模块,放在前面
import person from './module3 针对默认暴露
import {fun1, fun2} from './module2' 针对分别和统一暴露,解构对象的方式
1) 创建项目结构
```
|-js
|-libs
|-src
|-module1.js
|-module2.js
|-module3.js
|-main.js
|-index.html
|-package.json
|-.babelrc(自定义文件)
```
项目下定义package.json文件
```
{
"name" : "es6-babel-browserify",
"version" : "1.0.0",
}
```
!! 项目下定义.babelrc文件
```
{
"presets": ["es2015"]
}
```
2) 安装babel-cli, babel-preset-es2015和browserify
* npm install babel-cli browserify -g
* npm install babel-preset-es2015 --save-dev
* npm install browserify --save-dev
3) 编码
* 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]
```
module2.js
let data = 'module2 data'
function fun1() {
console.log('module2 fun1() ' + data);
}
function fun2() {
console.log('module2 fun2() ' + data);
}
export {fun1, fun2}
```
* 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);
```
4) 编译
* 使用Babel将ES6模块化编译为ES5的CommonJS模块化: babel js/src -d js/libs
* 使用Browserify编译js : browserify js/libs/main.js -o js/libs/bundle.js
5) 页面中引入测试
```
<script type="text/javascript" src="js/lib/bundle.js"></script>
```
6) 引入第三方模块(jQuery)
1). 下载jQuery模块:
* npm install jquery@1 --save
2). 在app.js中引入并使用
```
import $ from 'jquery'
$('body').css('background', 'red')
```
5.模块化在浏览器端运行(ADM) 基本不用
//定义没有依赖的模块
define(function(){
return 模块
})
//定义有依赖的模块
define(['module1', 'module2'], function(m1, m2){
return 模块
})
//引入模块
require(['module1', 'module2'], function(m1, m2){
使用m1/m2
})
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的模块代码
1. dataService.js
//定义没有依赖的模块
define(function () {
let msg = 'atguigu.com'
function getMsg() {
return msg.toUpperCase()
}
return {getMsg}
})
2. alerter.js
//定义有依赖的模块
define(['dataService'], function (dataService) {
let name = 'Tom2'
function showMsg() {
alert(dataService.getMsg() + ', ' + name)
}
return {showMsg}
})
4) 模块引入在主js上: main.js
!! (function () {
//配置
requirejs.config({
//基本路径,以js目录的父目录为参考结合baseUrl和paths
baseUrl: "js/",
//模块标识名与模块路径映射(后缀不加.js,系统默认添加,自己加报错)
paths: {
"alerter": "modules/alerter",//以main.js文件为参考路径
"dataService": "modules/dataService",
}
})
//引入使用模块
requirejs( ['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'//注意:jquery的q要小写,因为jQuery在暴露时候就是小写
}
```
* 在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.js导入项目
* js/libs/angular.js
* 在main.js中配置
```
(function () {
require.config({
//基本路径
baseUrl: "js/",
//模块标识名与模块路径映射
paths: {
//第三方库
'jquery' : './libs/jquery-1.10.1',
'angular' : './libs/angular',
//自定义模块
"alerter": "./modules/alerter",
"dataService": "./modules/dataService"
},
!! // AMD配置不兼容angular的模块,需用exports来暴露
shim: {
'angular' : {
exports : 'angular'
}
}
})
//引入使用模块
require( ['alerter', 'angular'], function(alerter, angular) {
alerter.showMsg()
console.log(angular);
})
})()
```
6.模块化在浏览器端运行(CDM) 基本不用
//定义没有依赖的模块
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()
})
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')// 必须./开头 参考index路径
</script>
```