Javascript模块化

一、模块化的理解

1.什么是模块和模块化

  • 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并进行组合在一起块的内部数据/实现是私有的,只是向外部暴露一些接口(方法)与外部其它模块通信

模块化进化史

  • 全局Function模式(存在的问题:全局被污染,很容易存在命名冲突)
/*全局函数 将不同功能封装成不同的全局函数*/
let msg = 'test'

function foo() {
  console.log("foo",msg);
}

function bar() {
  console.log("bar",msg);
}
  • 简单封装:Namespace模式(减少全局上的变量数目,本质是对象,不安全,对象的属性可以随意被拿到并且更改)
/*Namespace模式,简单对象封装*/

let obj = {
  msg:"test",
  foo(){
    console.log("foo",this.msg);
  }
}
  • 匿名闭包:IIFE模式(函数是JavaScript唯一的Local Scope)
/*IIFE模式,匿名函数自调用(闭包)*/

(function () {
  let msg ="test";
  function foo(){
    console.log("foo",this.msg);
  }
  //向window添加一个module属性,将foo函数暴露出去
  window.module = {foo};
})()
  • 引入依赖:(模块模式,现代模块实现的基石)
/*引入依赖*/

(function (window,JQurey) {
  let msg ="test";
  function foo(){
    console.log("foo",this.msg);
  }
  //向window添加一个module属性,将foo函数暴露出去
  window.module = {foo};
  $('body').css('background','red');
})(window,JQurey)

2.为什么要模块化

  • 降低复杂度
  • 提高解耦性
  • 部署方便

3.模块化的好处

  • 避免命名冲突(减少命名空间污染)
  • 更好的分离,按需加载
  • 更高复用性
  • 高可维护性

4.页面引入加载script带来的问题

  • 请求过多
  • 依赖模糊
  • 难以维护

二、模块化规范

1.CommonJS

  • 每个文件都可当作一个模块
  • 在服务器端:模块的加载是运行时同步加载的
  • 在浏览器端:模块需要提前编译打包处理

基本语法

  • 暴露模块
    • module.exports = value(value代表任何的数据类型)
    • exports.xxx = value(value代表任何的数据类型)
    • 暴露的模块其实是一个exports对象
  • 引入模块
    • require(xxx)
      • 第三方模块:xxx为文件名
      • 自定义模块:xxx为模块文件路径

实现

  • 服务器端实现
  • 先创建三个模块
    在这里插入图片描述
  • 初始化package.json文件,在终端中进入到相应的目录,输入npm init ,初始化,第一个命名时不要出现大写字母和中文,其他的一直按确认就行。如果初始文件夹不是大写的和没有中文的,可以输入npm init -yes,之间初始化完成,自动生成package.json,当然也可以选择手动创建(注意:需要提前安装node.js,教程自行搜索)

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

  • 浏览器端实现
  • 创建下面的目录结构(src下的文件是上述例子的,这个文件夹存放的是源代码文件 ,package.json生成方法同上,package-lock.json是自动生成的)
    在这里插入图片描述
  • 先在index.html中引入app.js,在浏览器运行,浏览器并不认识require
    在这里插入图片描述
  • 这里需要安装一个包(全局和局部都要安装,注意前提是先安装了node.js)
    • 全局安装:npm i browserify -g
    • 局部安装:npm i browserify --save-dev
    • 安装完成会生成上图的文件,同时package.json中会多了一个配置
      在这里插入图片描述
  • 打包处理js
    • browserify js/src/app.js -o js/dist/bundle.js
    • 以 -o 为界,前面是要打包的文件的路径,后面是打包完成后的文件路径
    • 要在对应项目的根路径下,否则会找不到相应的路径
    • 一旦改动了相应的js文件,就要重新打包
      在这里插入图片描述
  • 此时dist中会自动生成已打包好的文件
    在这里插入图片描述
  • 在index.html中引入该文件,在浏览器成功运行
    在这里插入图片描述

2.AMD

  • Asynchronous Module Definition(异步模块定义)
  • AMD专门用于浏览器端,模块的加载是异步的

基本语法

  • 定义暴露模块
//定义没有依赖的模块
define(function(){
	return模块
})
//定义有依赖的模块,//m1与module1对应
define(['module1', 'module2'],function(m1, m2){
	return模块
})
  • 引入使用模块
require(['module1', 'module2'], function(m1, m2){
	使用m1/m2
})

实现

  • 需要依赖一个库:Require.js
  • https://requirejs.org/
  • 下载完成后需要在项目中引入
    在这里插入图片描述
    在这里插入图片描述
  • 不使用AMD进行模块化(采用引入依赖)
  • 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);

  • main.js
(function (alerter) {
  alerter.showMsg();
})(alerter);
  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script  src="js/modules/dataService.js"></script>
<script  src="js/modules/alerter.js"></script>
<script  src="js/main.js"></script>
</body>
</html>

在这里插入图片描述

  • 运行截图
    在这里插入图片描述
  • 使用AMD进行模块化(自定义模块)
    在这里插入图片描述
  • dataService.js
//定义没有依赖的模块
define( function (){
  let name = 'dataService.js ';
  function getName( ) {
    return name;
  }

//暴露模块
return {getName};
});

  • alerter.js
//定义有依赖的模块
define( ['dataService'],function(dataService){
  let msg = 'alerter.js ' ;
  function showMsg() {
    console.log(msg,dataService.getName());}
  //暴露模块
  return {showMsg};
});

  • main.js
(function () {
  requirejs.config({
  baseUrl: 'js/',//基本的路径
  paths: {//配置路径
    dataService: './modules/dataService',
    alerter: './modules/alerter',
  }
  });
  requirejs( [ 'alerter' ], function (alerter) {
    alerter.showMsg();
  })
})();

在这里插入图片描述

  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script data-main="js/main.js" src="js/libs/require.js"></script>
</body>
</html>

在这里插入图片描述

  • 运行截图
    在这里插入图片描述

3.CMD(了解)

  • Common Module Definition(通用模块定义)
  • 专门用于浏览器端,模块的加载是异步的模块使用时才会加载执行
  • 官网已经打不开了,所以所需要的依赖库已经下载不了,就当作了解

基本语法

  • 定义暴露模块
/定义没有依赖的模块
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()
})

4.ES6

  • 依赖模块需要编译打包处理
  • 基本语法
    • 导出模块:export
    • 引入模块:import zzz from xxx
      • zzz,在分别暴露和统一暴露中,暴露的是什么,zzz就是什么,默认暴露中可以自己命名
      • 第三方模块:xxx为文件名
      • 自定义模块:xxx为模块文件路径
  • 实现
  • 创建以下目录结构
    在这里插入图片描述
  • 初始化package.json
    在这里插入图片描述
  • 安装babel-cli, babel-preset-es2015和browserify
    • npm install babel-cli browserify -g
    • npm install babel-preset-es2015 --save-dev
      preset预设(将es6转换成es5的所有插件打包)
  • 定义.babelrc文件,创建一个文件,命名为.babelrc
    在这里插入图片描述
    在这里插入图片描述
  • module1.js
//分别暴露
export function foo() {
  console.log( 'foo() module1' );
}
export function bar() {
  console.log("bar() module1");
}

export let arr = [1,2,3,4]
  • module2.js
//统一暴露
function fun(){
  console.log( 'fun( ) module2 ' );
}
function fun2(){
  console.log( " fun2() module2");
}
export {fun,fun2};

  • module3.js
//默认暴露可以暴露任意数据类型,暴露什么数据接收到的就是什么数据.
// export default vaLue;
//默认暴露只能写一次
export default () => {
  console.log("我是默认暴露的箭头函数");
}

  • main.js
import {foo, bar} from './module1';
import {fun, fun2} from './module2';
import module3 from './module3 ';

foo();
bar();
fun();
fun2();
module3();

  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script src="js/dist/bundle.js"></script>
</body>
</html>
  • 直接引入main.js,浏览器不能识别import
    在这里插入图片描述
  • 对其进行编译,将es6语法转成es5
  • 使用Babel将ES6编译为ES5代码(但包含CommonJS语法) : babel js/src -d js/build
  • 以-d分界,左边是需要转换的路径,它会找到该路径下所有的js文件,右边是转换后文件的存放路径,具体放哪可以自己定义,这个命令可以创建文件夹
    在这里插入图片描述
    在这里插入图片描述
  • 此时若引入build中的main.js,浏览器不能识别require
    在这里插入图片描述
  • 使用Browserify编译js : browserify js/build/main.js -o js/dist/bundle.js
  • 这个命令不能创建文件夹,要自己手动创建
    在这里插入图片描述
    在这里插入图片描述
  • 此时引入dist下的bundle.js,成功执行
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值