跳到主要内容

ESModule 模块化

模块化技术对比

模块化技术实现者
AMDRequireJS
CMDSeaJS
CommonJSNode 社区
ESModuleECMA 官方

模块化的核心在于将脚本划分为一个个小块(chunk),使其可以在任意脚本中灵活引用。下面我们重点介绍 ECMA 官方提出的 ESModule 标准。

导出模块

直接导出(export)

我们可以使用export关键字直接导出一个函数:

export function add(a, b) {
return a + b;
}

export function minus(a, b) {
return a - b;
}

export function multiply(a, b) {
return a * b;
}

export function divide(a, b) {
return a / b;
}

集中导出(export)

除了逐个导出,我们还可以将多个模块集中在一起导出:

function add(a, b) {
return a + b;
}

function minus(a, b) {
return a - b;
}

function multiply(a, b) {
return a * b;
}

function divide(a, b) {
return a / b;
}

export { add, minus, multiply, divide };

默认导出(export default)

如果我们希望导出一个默认对象,可以使用export default:

export default {
add(a, b) {
return a + b;
},

minus(a, b) {
return a - b;
},

multiply(a, b) {
return a * b;
},

divide(a, b) {
return a / b;
},
};

导入模块

解构导入

针对使用export{}集中导出的模块,我们可以使用解构的方式按需导入:

import { add, minus, multiply, divide } from './math';

导入默认模块

如果模块使用了export default默认导出,则可以为导入的模块自定义名称:

import math from './math';
const { add, minus, multiply, divide } = math;

实战案例:简易计算器

接下来,我们使用 ESModule 来实现一个简易的计算器。

HTML

<div id="calculator">
<div class="display"></div>
<h1 id="result">0</h1>
<input type="number" id="num1" />
<input type="number" id="num2" />
<div class="button-group">
<button>+</button>
<button>-</button>
<button>*</button>
<button>/</button>
</div>
</div>
<script type="module" src="./app.js"></script>

app.js

import math from './math';
const { add, minus, multiply, divide } = math;

(() => {
const num1Input = document.querySelector('#num1');
const num2Input = document.querySelector('#num2');
const buttonGroup = document.querySelector('.button-group');
const resultText = document.querySelector('#result');

const init = () => {
bindEvents();
};

function bindEvents() {
buttonGroup.addEventListener('click', handleButtonClick, false);
}

function handleButtonClick(e) {
const target = e.target;
const tagName = target.tagName.toLowerCase();
if (tagName === 'button') {
const operator = target.innerText;
resultText.innerText = calculate(operator);
}
}

function calculate(operator) {
const num1 = Number(num1Input.value);
const num2 = Number(num2Input.value);

switch (operator) {
case '+':
return add(num1, num2);
case '-':
return minus(num1, num2);
case '*':
return multiply(num1, num2);
case '/':
return divide(num1, num2);
default:
return '';
}
}

init();
})();

在上面的代码中,我们将数学运算函数单独放在math模块中,并在app.js中导入使用。当点击计算器的运算符按钮时,会动态计算两个输入框的值,并将结果显示在resultText元素上。

这个案例虽然简单,但很好地展示了如何使用 ESModule 进行模块化开发。将不同功能的代码划分到独立的模块中,可以提高代码的可维护性和可重用性。在实际项目中,我们可以将复杂的业务逻辑、通用工具函数等封装成模块,在需要的地方导入使用,使代码结构更加清晰。