• js模块化


    第1章:模块化入门

    1.1.理解什么是模块

    1. 将一个复杂的程序依据一定的规则拆分成单个文件,并最终组合在一起
    2. 这些拆分的文件就是模块,模块内部数据是私有的,只是向外部暴露一些方法与外部其它模块通信

    1.2.为什么要模块化?

    1. 降低复杂度,提高解耦性
    2. 避免命名冲突
    3. 更好的分离,按需加载
    4. 更高复用性,高可维护性

    1.3模块化概念带来的问题

    1. 请求过多
    2. 依赖模糊
    3. 难以维护

    第2章:模块化规范

    前言:一个大的项目必定会使用模块化技术,使用模块化就会使用相应的模块化规范,现在比较流行的模块化规范有以下2种: CommonJS、ES6e

    2.1.CommonJS

    2.1.1规范

    1. 官网: http://wiki.commonjs.org/wiki/Modules

    2. 每个文件都是一个模块。

    3. CommonJS模块化的代码既可在服务端(node)运行,也可在浏览器(browser浏览器)端运行。(es6模块化只能写浏览器端)

    4. 服务器端:模块化的代码可直接运行。

    5. 浏览器端:模块化的代码要经过 Browserify (http://browserify.org)编译(类比:es6的箭头函数不能直接被浏览器所识别,需要借助babel编译)。

    2.1.2基本语法

    1.暴露语法:
    1. 第一种方式: module.exports = value

    2. 第二种方式: exports.xxx = value

    2. 引入语法:
    1. 引入第三方模块:require(xxx),xx为模块名

    2. 引入自定义模块: require(xxx),xxx为模块文件路径

    3.备注:内置关系

    在这里插入图片描述

    验证:module.exports == exports

    在这里插入图片描述

    module.exports使用示例

    module1.js使用module.exports语法,暴露出一个对象。app.js中引入该暴露的对象,并使用

    module1.js
    
    /* 
    	module1使用module.exports = xxxx 去暴露,xxx就是暴露的内容
    */
    //没有暴露data和msg(被保护了)
    const data = 'atguigu'
    const msg = 'hello'
    
    module.exports = {
    	showData (){
    		console.log(data);
    	},
    	showMsg(){
    		console.log(msg);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    app.js
    // 暴露的本质是module.exports的内容
    // 引入的内容是什么,取决于暴露的是什么
    const m1 = require('./module1') //引入自定义模块
    m1.showData()
    m1.showMsg()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    exports使用示例

    module2.js使用exports语法,往暴露的对象中添加属性。app.js中引入该暴露的对象,并使用

    module2.js
    /* 
    	module2使用exports.xxxxx = value 去暴露,value就是暴露的内容,xxxxx是他的名字
      (注意:module.exports和exports不能混用,若混用了,以module.exports
             其实,最终暴露的对象,只认module.exports,只不过刚开始exports的引用初始值就被赋值为module.exports了)
    */
    
    exports.data  = 'atguigu2'
    exports.msg = 'hello2'
    
    exports.sum = function (a,b){
    	console.log(a+b);
    }
    
    exports.sub = function (a,b){
    	console.log(a-b);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    app.js
    const m2 = require('./module2') //引入自定义模块
    const m22 = require('./module2') //引入自定义模块
    
    console.log(m2==m22) // true
    
    console.log(m2.data);
    console.log(m2.msg);
    m2.sum(1,2)
    m2.sub(3,4)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    第三方模块使用示例

    第一步

    npm init --yes,在当前文件夹中,初始化包管理配置(会生成package.json文件,安装包时,会将包安装在当前文件的node_modules文件夹中)
    (当使用require引入第三方模块时,会先从当前文件夹中寻找node_modules文件夹,并从中找到对应的模块,如果没找到,则会到当前文件夹的父文件夹中寻找node_modules文件夹,并从中找到对应的模块)

    第二步

    npm install uniq,安装uniq包

    第三步

    引入,并使用

    // app.js
    const uniq = require('uniq') // 引入第三方模块模块(只需要写模块名)
    const arr = [1,3,3,4,2,5]
    console.log(uniq(arr));
    
    • 1
    • 2
    • 3
    • 4

    2.1.3 commonJs在浏览器使用

    问题引入

    上述符合commonJs模块化规范的代码,使用node命令能够正常执行,但是浏览器并不能识别commonJs模块化的语言,需要使用browserify来编译之后,才能被浏览器使用,browserify官网:https://browserify.org/。

    //
    const data = 'atguigu'
    const msg = 'hello'
    
    module.exports = {
    	showData (){
    		console.log(data);
    	},
    	showMsg(){
    		console.log(msg);
    	}
    }
    
    // 
    const m1 = require('./module1') // 引入自定义模块
    const uniq = require('uniq')    // 引入第三方模块
    
    m1.showData()
    m1.showMsg()
    const arr = [1,3,3,4,2,5]
    console.log(uniq(arr));
    
    // 
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>Document</title>
    	</head>
    	<body>
    		<!-- 直接引入app.js,将不可用,因为app.js使用了CommonJs模块化语法,浏览器并不能识别 -->
    		<script type="text/javascript" src="./app.js"></script>
    	</body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    browserify使用

    首先需要安装browserify

    # 全局安装
    npm i browserify -g 
    
    • 1
    • 2

    编译指定文件

    browserify ./app.js -o ./build.js
    
    • 1

    在index.html中引入build.js

    DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>Documenttitle>
    	head>
    	<body>
    		<script type="text/javascript" src="./build.js">script>
    	body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.2 ES6模块化规范

    (ES6就是ES2015,es6推出新语法、模块化规范、Promise,es7提出async/await)

    2.2.1 规范

    1. 每个文件都是一个模块。

    2. 借助 Babel(能把ES6代码编译成ES5的代码,jsx语法转为js)和Browserify依次编译代码,才能在浏览器端运行。

    3. Babel中文网: https://www.babeljs.cn/

    2.2.2 基本语法

    1. 暴露模块:

    1. 分别暴露: export 暴露内容

    2. 统一暴露: export {暴露内容1,暴露内容2}

    3. 默认暴露: export defalut 暴露内容

    2. 引入模块:

    1. 方法1: import {xxx,yyy} from ‘./module1’

    2. 方法2: import module3 from ‘./module3’

    3.使用规则:

    1. 若使用分别暴露、统一暴露的方式暴露内容,那么就要用方法1引入。

    2. 若使用默认暴露的方式暴露内容,那么就要用方法2引入。

    ES6暴露使用示例

    问题引入
    // 
    /* 
    	module1中使用【分别暴露】
    */
    export const data = 'atguigu'
    export const msg = 'hello,0826'
    
    export function showData(){
    	console.log(data);
    }
    export function showMsg(){
    	console.log(msg);
    }
    
    /*错误写法
    const mistake = 'mistake '
    export mistake
    */
    
    // 
    import {data,msg,showData,showMsg} from './module1'
    console.log(data)
    console.log(msg)
    showData()
    showMsg()
    
    // 
    /* 直接引入app.js,因为app.js中使用了es6的模块化语法,而不能识别报错 */
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>Document</title>
    	</head>
    	<body>
    		<script type="text/javascript" src="./app.js"></script>
    	</body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    babel使用
    第一步:准备相关依赖包

    准备相关依赖包(为编译代码做准备)

    • 全局安装: babel-cli、Browserify,执行命令如下:

      npm install babel-cli browserify -g
      
      • 1
      • 局部安装:babel-preset-es2015(es2015就是es6)
        npm install babel-preset-es2015
        
        • 1
    • 定义 .babelrc 文件(前面有.)

      {
      	"presets":["es2015"]
      }
      
      • 1
      • 2
      • 3
    第二步:编译代码
    • 进入目录,使用Babel将ES6编译为ES5代码:
      # 将当前文件夹中的src下的文件,通过babel 编译到 当前的build文件夹下
      babel ./src -d ./build
      
      • 1
      • 2
    • 继续使用Browserify编译上一步的js
      (因为上一步将es6的模块化语法转为了commonJs模块化语法,浏览器依然无法识别其中的require关键字):
      browserify ./build/app.js -o ./build/index.js
      
      • 1
    第三步:在页面中引入测试
    
    DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>Documenttitle>
    	head>
    	<body>
    		<script type="text/javascript" src="../build/build.js">script>
    	body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    ES6模块化操作流程总结
    1. 创建文件结构如下
    			-3_ES6_modular
    				-src
    					-app.js
    					-module1.js
    					-index.html
    				-.babelrc,内容如下:
    
    					{
    						"presets": ["es2015"]
    					}
    
     2. 准备相关包
    			npm install babel-cli browserify -g 
    			npm install babel-preset-es2015
    
     3. babel编译为ES5,命令如下:babel ./src -d ./build
    		browserify继续编译,命令如下:browserify ./build/app.js -o ./build/build.js
    		备注:命令不要记!!我们学习的是模块化的暴露、引入语法,不是命令,以后也不敲命令。
    		
     4. index.html页面中引入build/build.js
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    ES6多种暴露使用示例

    分别暴露
    // 
    /* 
    	module1中使用【分别暴露】
    */
    
    export const data = 'atguigu'
    export const msg = 'hello,0826'
    
    export function showData(){
    	console.log(data);
    }
    export function showMsg(){
    	console.log(msg);
    }
    
    // 
    /* 
    	module2中使用【分别暴露】,但暴露了一个和module1重名的一个data
    */
    export const data = '北七家镇宏福科技园'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    统一暴露
    /* 
    	module3中使用【统一暴露】
    */
    
    const school = '尚硅谷'
    const person = {
    	name:'老刘',
    	age:19,
    	sex:'女'
    }
    function getLaoliu(){
    	console.log(person);
    }
    
    //统一暴露(精简版)---用的多
    export {school,person,getLaoliu}
    
    //统一暴露(完整版) (所以上面精简版这不是对象的简写形式)
    // export {school as a,person as b,getLaoliu as c}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    默认暴露
    /* 
    	module4中使用【默认暴露】-----只能暴露一次!!!!
    	(右侧得为一个表达式,所谓的表达式就是,能获得值,比如左边使用var xxx = 右边,能接收到值)
    */
    export default {
    	name:"wc",
    	age:5,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    多种暴露
    // 
    // 同时使用多种暴露方式
    //使用【分别暴露】
    export const teacher1 = {name:'强哥',age:15}
    export const teacher2 = {name:'歌神',age:17}
    
    //使用【统一暴露】
    const stu1 = {name:'王宇',age:18}
    const stu2 = {name:'宇航',age:19}
    export {stu1,stu2}
    export {stu1 as stu11,stu2 as stu22}
    
    //使用【默认暴露】
    export default {
    	school:'尚硅谷',
    	address:'宏福科技园',
    	subjects:['前端','java','大数据']
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    引入模块
    // 
    //引入【分别暴露】的模块(这里的都不是解构赋值,根本不符合解构赋值的语法)
    import {data,showData,showMsg} from './module1'
    
    //引入【分别暴露】的模块+重命名
    import {data as data2} from './module2'
    
    //引入【分别暴露】的模块+打包引入
    import * as module1 from './module1'
    
    //引入【统一暴露】的模块(统一暴露和分别暴露,最后引入的方式都是一样的)
    import {school,person,getLaoliu} from './module3'
    
    //引入【默认暴露】的模块
    import module4 from './module4'
    
    //引入多种暴露方式的模块(module5是默认暴露,其它是分别暴露或统一暴露)
    import module5,{teacher1,teacher2,stu1,stu2,stu11,stu22} from './module5'
    console.log(module5);
    console.log(teacher1);
    console.log(teacher2);
    console.log(stu1);
    console.log(stu2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    Batch normalization和Layer normalization
    30组易混易错词汇辨析,柯桥成人英语培训哪家好
    web前端之零碎知识点、字符串、数组、基础知识
    图像边缘检测与图像分割常用算法研究分析-含Matlab代码
    [附源码]JAVA毕业设计健康生活网站(系统+LW)
    域渗透04-漏洞(CVE-2020-1472)
    metersphere 创建场景, 自动动态变换参数值,实现接口自动化测试。
    【Hack The Box】windows练习-- Timelapse
    uboot-重定位中断向量表 relocate_vectors 函数
    C++核心编程(三十)容器(vector)
  • 原文地址:https://blog.csdn.net/qq_16992475/article/details/128211396