Webpack学习笔记 01、Module模块系统

举报
长路 发表于 2022/11/28 21:42:56 2022/11/28
【摘要】 文章目录前言一、Module出现的原因1.1、最初引入js文件的方式(原始引入与立即调用函数表达式方式)1.2、使用Module模块系统管理(初次使用)二、Module模块方式与使用前提条件2.1、引入Module模块方式(两种)2.2、前提条件三、Module的两种导出与导入方式一:export default导出与import导入(只能单个)方式二:export导出与import引入(单、多个

@[toc]

前言

本篇博客是关于webpack的module模块系统,若文章中出现相关问题,请指出!

所有博客文件目录索引:博客目录索引(持续更新)

一、Module出现的原因

1.1、最初引入js文件的方式(原始引入与立即调用函数表达式方式)

原始方式

image-20210624223048754

将1.js以及2.js文件引入到html文件中,最开始的方式为:

1.js

const num1 = 10;

2.js

const num2 = 100;

exer.html

<!-- 使用script标签来引入js文件 -->
<script src="./modules/1.js"></script>
<script src="./modules/2.js"></script>
<script>
    console.log(`num1=${num1}`)
    console.log(`num2=${num2}`)
</script>

image-20210624223421418

说明:这种引入js的方式有很多弊端,例如大量的变量定义存在于一个上下文中,并且若是有多个js文件都需要进行一个个引入!


稍微优化后的引入方式:通过立即调用函数表达式

使用该种方式能够将对应想要暴露出去的对象或变量放置到全局变量window对象中:对于全局变量定义形成可控

1.js

(function () {
    const num1 = 10;
    const num11 = 11;
    //仅仅暴露出去num11
    window.num11 = num11;
})();

2.js

(function () {
    const num2 = 100;
    //暴露出去num2
    window.num2 = num2;
})();

exer.html

<!-- 使用script标签来引入js文件 -->
<script src="./modules/1.js"></script>
<script src="./modules/2.js"></script>
<script>
    //暴露出来的仅仅只有两个变量num11,num2,对于num1并没有暴露出来,存在于闭包中
    console.log(`num11=${num11}`)
    console.log(`num2=${num2}`)
    console.log(`num1=${num1}`)
</script>

image-20210624224232544

**好处:**对于我们想要暴露出去的指定对象或变量能有很好的可控性,但是这就需要你每个js文件都要写()()立即函数表达式。

缺点(待解决问题):模块化的问题,对于某个模块想要使用另一个模块中的指定对象就需要通过window的全局变量来操控,这就对项目中模块与模块之间使用出现了很大的问题。需要出现一种模块系统来进行解决问题,消除全局变量以及管理加载顺序等等,这就需要使用到了Module模块系统,ES6就推出了该系统!!!



1.2、使用Module模块系统管理(初次使用)

下面是通过使用Module模块系统管理:使用export xxx 以及 import xxx进行使用

1.js

const num1 = 10;
export default num1;

2.js

// 引入模块,并输出变量
import num1 from './1.js'
console.log(`num1=${num1}`);

const num2 = 100;
//导出num2
export default num2;

exer.html

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    // 引入模块得到num2
    import num2 from './modules/2.js'
    console.log(`num2=${num2}`);
    //测试输出其他模块
    console.log(num1);
</script>

image-20210624234122199



二、Module模块方式与使用前提条件

2.1、引入Module模块方式(两种)

方式一:通过script标签来引入模块,该种方式不能够得到对应的模块输出内容

<script src="./modules/2.js" type="module"></script>

方式二:使用import方式,可以获取到对应模块导出的内容

import num2 from './modules/2.js'


2.2、前提条件

ES6出现模块系统来方便进行管理!ES Module就是RequireJS seaJS的原生版本了,就是进行模块管理的!

使用Module模块系统的前提条件

  1. 需要搭建服务器的环境,让Module模块系统能够进行正常的执行。(本地直接打开页面是不行的,如使用file协议打开的就会出现下面的报错)
    • image-20210624234556507

对于搭建服务器的环境比较简单的方式使用vscode插件:live Server即可!!!



三、Module的两种导出与导入

导出(export)的东西可以被导入(import),并被访问到!

注意:一个模块没有导出也可以将其导入,被导入的代码都会执行一遍,也仅仅会执行一遍!


方式一:export default导出与import导入(只能单个)

多次引入相同的模块:只会执行一次该js文件

2.js

const num = 10;
console.log(num);

// 导出
export default num;

测试:

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    // 多次引入同一个模块中的js文件,该文件只会执行一次!
    import num from './modules/2.js';
    import num1 from './modules/2.js';
    import num2 from './modules/2.js';
</script>

image-20210626164113449


基本要求(3点)

1、一个模块中只能有一个export default,否则会报语法错误:Uncaught SyntaxError: Identifier '.default' has already been declared

2、导出的类型可以为任意类型(基本类型、引用类型都可),可以写成表达式形式(或者匿名表达式)也是可以的。

3、配合引用import时对于导出的值可以随意起别名。

测试

2.js

const num = 10;
console.log(num);

//测试2:分别为基本类型、匿名表达式、对象
export default num;
// export default function () { console.log("hello"); }
// export default { name: 'changlu', age: 18 };

exer.html

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    // 多次引入同一个模块中的js文件,该文件只会执行一次!
    import num from './modules/2.js';
    console.log(num);
</script>


方式二:export导出与import引入(单、多个)

基本使用

export=>import:可以导出单个或者多个,导出时不能使用别名必须使用导出时的名称

注意

  1. 导入时应当与导出时的名称一致并且需要被**{}包裹**。
  2. 不能导出匿名函数、箭头函数等一些没有变量名的!

导出单个的方式

// 方式一:通过声明形式导出
export const num = 2;  //对应导入:import {num} from './module/2.js'
// 方式二:直接导出变量形式
export { num };  //对应导入:import {num} from './module/2.js'

导出多个方式

2.js

const num = 1;
const str = 'changlu';
const obj = { name: 'cl' }

// 导出多个
export { num, str, obj };

方式一:允许一个个单独导出

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    // 多次单独导出指定的属性
    import { num } from './modules/2.js';
    import { str } from './modules/2.js';
    import { obj } from './modules/2.js';
    console.log(num, str, obj);
</script>


导出导入时起别名

介绍

无法起别名情况:声明式的,如:export const num = 1,不能取别名!

可以起别名情况:导入与导出都可以设置别名,如export {num as bieming}import {num as bieming} from 'xxx'


示例

2.js

const num = 10;
export { num };

exer.html

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    // 起了别名之后,别名num1才有对应的值
    import { num as num1 } from './modules/2.js';
    console.log(num1);
    console.log(num);
</script>

image-20210626223016490



整体导入(导入到一个对象中,* as obj)

示例

2.js

const num = 10;
const str = 'changlu';
const arr = [1, 2, 3];

// 同时导出多个
export { num, str, arr };

exer.html

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    // 整体多个值导入到一个对象中
    import * as obj from './modules/2.js';
    console.log(obj);
    //可直接通过键来获取到对应的值
    console.log(obj.arr);
    console.log(obj.num);
    console.log(obj.str);
</script>

image-20210626223534893



export与eport default同时导出

说明:也就是说两种导出方式能够一起使用,只不过有限制就是export default一个模块中只能够使用一次!若是一起导出时,导入指定模块需要将export default先导入,如下!

2.js

const num = 10;
const str = 'changlu';
const arr = [1, 2, 3];

//使用export导出多个
export { num, str, arr };
//使用export default导出1个
export default 30;

exer.html

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    // 注意了若是引入的模块中使用了export default,那么就必须先引入该expert default的值
    import num, * as obj from './modules/2.js';
    //输出export default导出的值
    console.log(`export default的值为:${num}`);
    //输出export导出的值
    console.log("export导出的对象集合为:");
    console.log(obj);
    console.log(obj.arr);
    console.log(obj.num);
    console.log(obj.str);
</script>

image-20210626224629256



四、Module的注意事项

4.1、模块顶层的this指向

结论:在模块中,顶层的this指向undefined,这就能够很好的解决模块化的问题!

示例

2.js

console.log(this);

exer.html

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    // 注意了若是引入的模块中使用了export default,那么就必须先引入该expert default的值
    import './modules/2.js';
</script>

image-20210626225537356



4.2、import关键字和import()函数

import关键字的使用(自动提升,但是不能够进行逻辑判断执行引入)

import:具有提升效果,会将该语句提升到模块的头部,率先执行。也就是说import执行的时候,代码还没有执行。

  • importexport命令只能在模块的顶层不能在代码块中执行。

示例

2.js

console.log(`模块中的开始执行......,输出this为:${this}`);

exer.html

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    console.log("hello");
    console.log("changlu!");
    //故意将引入模块放在前面两句console.log()后输出
    import './modules/2.js';
</script>

image-20210626235618051

缺点:对于我们想要适配pc端或是手机端时,选择哪个来进行引入仅仅使用import关键字是不够的,因为一旦使用import关键字的话就会直接进行执行,而不是根据逻辑来进行判断引入哪个js文件!下面是示例实际上是不允许的:

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    const pc = true;
    //是不允许以下这么进行逻辑判断引入js的!会报错:Uncaught SyntaxError: Unexpected string
    if (pc) {
        import './modules/pc.js';
    } else {
        import './modules/mobile.js'
    }
</script>

import()函数

import():使用该函数能够配合逻辑判断引入,而不是像import一样具有提升效果直接引入,弥补了import关键字的缺点!

示例

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    const pc = true;
    //通过使用import()函数就能够进行逻辑判断后导入指定的js模块
    if (pc) {
        import('./modules/pc.js').then(module => { console.log(module) });
    } else {
        import('./modules/mobile.js').then(module => { console.log(module) });
    }
</script>

image-20210627001140330



4.3、导入导出的复合写法

介绍

复合写法:就是说一条语句能够既导入又导出的操作!缺点就是不能对导出的变量执行任何操作!!!

用途:就是达到了中转站的效果!

注意点:复合语句中export后的值无论是单个还是多个必须是{}包裹,否则会报语法错误,并且不能执行对导出的变量进行任何操作!


示例

mobile.js

export const num = 10;

pc.js

//export的复合写法
export { num } from './mobile.js'
//复合写法相当于执行了引入与导出两步操作
//①import { num } from './mobile.js'
//②export { num } from './mobile.js'

//注意:不能有任何对num的操作,例如输出、修改等等操作
// console.log(num);

exer.html

<!-- 对于引入模块的需要设置type="module" -->
<script type="module">
    import { num } from './modules/pc.js'
    console.log(num);
</script>

image-20210627001954175



五、实际应用

一般的话js代码都是基于对象来进行编写的,一般将一个类或者常量或者说是单独的功能模块都使用Module模块系统来进行抽离,有利于代码的可扩展性!!!

比如说抽离的内容如:常量以及默认参数一块、某个设置默认参数对象、类或者说单独的功能模块我们都可以进行拆分!!!

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。