ES6模块化

109 阅读4分钟

从这学期开始学了vue3,并且写了一些项目,但是到现在还没搞清楚什么时候用export default,什么时候用export,可能我当时JavaScript基础学的不扎实。
下面记录一下ES6模块化是什么并且怎么用。
视频建议看(尚硅谷天禹老师)的视频:www.bilibili.com/video/BV13W…

1.什么是模块化

  • 将程序按照一定的规则拆分成多个文件。
  • 拆分出来的每个文件就是一个模块
  • 同时通过一些手段,可以把模块内的指定数据交出去,供其他模块复用

这个很好理解,我当时写个人博客项目的时候也是根据功能的不同,把前后端数据交互的api分成了好几个js文件:

image.png 下面举几个例子:
category.js image.png tag.js

image.png 你觉得把这两个js文件放到一个.js文件好呢还是分成两个.js文件好呢,当然是后者。

2.为什么需要模块化

  • 如果不进行合理的模块化,导致全局污染问题

比如有两个js文件,school.js和student.js:
school.js

const name = 'xxx学院'
const slogan = '学以致用,快乐成长'

function getTel() {
    return '010-12345678'
}

function getCities() {
    return ['北京', '上海', '广州', '深圳']
}

student.js

const name = "John"
const motto = "Don't worry, be happy!"

function getTel() {
    return "123-456-7890"
}

function getHobby() {
    return ["reading", "swimming", "hiking"]
}

index.js中进行引入:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <script src="./student.js"></script>
    <script src="./school.js"></script>
</body>
</html>

浏览器控制台已经报错了我:

image.png 相当于重复声明了两个变量name


  • 如果不进行合理的模块化,导致依赖混乱问题
  • 还会导致数据安全问题

3.ES6 MODULES

image.png

分别导出和引入所有

分别导出:
很简单,把想导出的东西前面加上export关键字:

export const name = "John"
export const motto = "Don't worry, be happy!"

export function getTel() {
    return "123-456-7890"
}

// 这个我不想交出去
function getHobby() {
    return ["reading", "swimming", "hiking"]
}

引入所有:

import * as student from './student.js'

console.log(student)

为了让node环境支持ES6 MODULES模块化规范,需要在当前目录下创建一个package.json文件:

{
  "type": "module"
}

node环境输出结果:

image.png 浏览器控制台输出结果:

html中导入index.js:需要写type="module"

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <script type="module" src="./index.js"></script>
</body>
</html>

image.png

export统一导出

统一导出用这种格式导出export { name, motto, getTel }

const name = "John"
const motto = "Don't worry, be happy!"

function getTel() {
    return "123-456-7890"
}

function getHobby() {
    return ["reading", "swimming", "hiking"]
}

// 统一导出
export { name, motto, getTel }

export default默认导出

注意:export default后面跟的是值,可以导出任意值或者变量

const name = "John"
const motto = "Don't worry, be happy!"

function getTel() {
    return "123-456-7890"
}

function getHobby() {
    return ["reading", "swimming", "hiking"]
}

// 默认导出
export default 900

image.png 导出多个值:

const name = "John"
const motto = "Don't worry, be happy!"

function getTel() {
    return "123-456-7890"
}

function getHobby() {
    return ["reading", "swimming", "hiking"]
}

// 统一导出多个值
export default { name, motto, getTel }

命名导入

可以通过{ xxx as 被导出的值 }命名导入
什么时候可以命名导入:统一导出和分别导出
student.js

const name = "John"
const motto = "Don't worry, be happy!"

function getTel() {
    return "123-456-7890"
}

function getHobby() {
    return ["reading", "swimming", "hiking"]
}

// 统一导出
export { name, motto, getTel }

index.js

import { name as stuName, motto as stuMotto, getTel as getStuTel } from './student.js';

console.log(stuName);
console.log(stuMotto);
console.log(getStuTel());

默认导入

默认导出的东西,不用写{}导入,可以直接导入:
student.js

const name = "John"
const motto = "Don't worry, be happy!"

function getTel() {
    return "123-456-7890"
}

function getHobby() {
    return ["reading", "swimming", "hiking"]
}

// 默认导出
/*export default name*/

// 或者导出多个变量
export default {name, motto, getTel}

index.js

import student from './student.js'

console.log(student)

也可以导入的时候取别的名字:

import studentInfo from './student.js'

console.log(studentInfo)

动态导入

动态导入就是只有需要使用该模块的时候才进行导入。
这个有点像vue-router的路由懒加载,当然vue-router导入的是.vue文件。
student.js

const name = "John"
const motto = "Don't worry, be happy!"

function getTel() {
    return "123-456-7890"
}

function getHobby() {
    return ["reading", "swimming", "hiking"]
}

export { name, motto, getTel }

index.js中动态导入:

const btn = document.querySelector('#btn')

// 需要异步导入,因为导入是有延迟的
btn.onclick = async () => {
    const student = await import('./student.js')
    console.log(student)
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="btn">获取student信息</button>

    <script type="module" src="./index.js"></script>
</body>
</html>

import直接导入

可能项目中我们导入的是一种导入就运行的函数什么的,这个时候我们可以直接导入: random.js

console.log(Math.random())

index.js中直接导入:

// 直接导入,不用写什么from等语句
import './random.js'

写过vue的朋友门这个应该很熟悉,比如main.js:

image.png 这里有几个.css文件进行了直接导入。

COMMONJS

CommonJS (CJS) 是 Node.js 采用的模块系统,它的设计初衷是用于服务器环境。

在 CommonJS 中,每个文件都是一个独立的模块。这个模块内部有一个 module 对象,module 对象上有一个 exports 属性,它就是我们要导出的东西。

直接赋值导出

// myUtils.js

// 导出一个函数
module.exports = function(a, b) {
  return a + b;
};

// 或者导出一个对象
module.exports = {
  name: 'utils',
  add: function(a, b) {
    return a + b;
  },
  subtract: function(a, b) {
    return a - b;
  }
};

导入 (require)

使用 require() 函数来导入其他模块,并接收 module.exports 导出的值。

// main.js

// 导入整个模块
const addFunction = require('./myUtils.js'); // 导入的是那个函数
const result1 = addFunction(5, 10); // 15

const utils = require('./myUtils.js'); // 假设 myUtils.js 导出的是对象
const result2 = utils.add(5, 10); // 15
console.log(utils.name); // 'utils'

// 导入属性
const constants = require('./myConstants.js');
console.log(constants.PI); // 3.14159

// 使用解构赋值(更简洁)
const { PI, VERSION } = require('./myConstants.js');
console.log(PI); // 3.14159
console.log(VERSION); // '1.0.0'