随着前端开发的不断发展,我们的项目变得越来越复杂,代码量也越来越大。找到全局变量的定义和使用变得越来越困难,这就导致了代码的维护难度大大增加。这时,我们就需要用到模块化开发。
ES6 (ECMAScript 2015) 是 JavaScript 的一次重大升级,其中包括了模块化支持。使用 ES6 模块化规范,我们可以将代码按功能模块划分,每个模块拥有独立的作用域,实现了代码的模块化开发,大大提高了代码的可维护性和可复用性。
接下来,我们将结合实际的开发案例,介绍 ES6 的模块化开发。
基础语法
ES6 模块化采用 export
和 import
关键字来定义和引用模块。
- 定义模块
使用 export
关键字来定义模块,如下:
// javascriptcn.com 代码示例 // demo.js export const name = 'Jack'; export function sayHello() { console.log('Hello'); } class Person { constructor(name, age) { this.name = name; this.age = age; } sayHi() { console.log(`Hi, I'm ${this.name}`); } } export { Person };
我们可以在 export
关键字后面跟随一个变量、函数或者类,作为模块的输出。
- 引用模块
使用 import
关键字来引用模块,如下:
// main.js import { name, sayHello, Person } from './demo.js'; console.log(name); // Jack sayHello(); // Hello const person = new Person('Tom', 18); person.sayHi(); // Hi, I'm Tom
import
关键字后面跟着花括号,里面列出了要引用的模块输出的名称,从指定的模块中导入相应的变量、函数或者类。
当我们省略花括号时,表示导入模块的默认输出,如下:
// javascriptcn.com 代码示例 // demo.js export default { name: 'Jack', age: 20 } // main.js import person from './demo.js'; console.log(person.name); // Jack
注意,在一个模块中,只能有一个默认输出。
实战案例
为了让大家更好地理解 ES6 模块化的应用,我们接下来就以一个类似于购物车的案例进行实现,并演示在不同的文件中如何构建和引用模块。
我们假设这是一个购物车的页面,这个页面要实现以下功能:
- 展示购物车中的商品列表,包括商品名称、价格、数量等信息;
- 实现添加商品、删除商品、修改商品数量等操作。
我们将根据这两个功能,将代码拆分成多个模块。
商品模块
首先,我们需要定义一个商品模块,其中包含了商品的名称、价格和数量等信息。
// javascriptcn.com 代码示例 // goods.js const goodsList = [{ name: 'iPhone 11', price: 5499, quantity: 1 }, { name: 'AirPods Pro', price: 1999, quantity: 1 }, { name: 'Apple Watch Series 5', price: 3999, quantity: 1 }]; export default { getGoodsList() { return goodsList; }, getTotal() { return goodsList.reduce((prev, curr) => prev + curr.price * curr.quantity, 0); } }
在商品模块中,我们使用 export default
关键字来定义该模块的默认输出,即一个包含商品列表和计算总价的对象。
购物车模块
接下来,我们需要定义一个购物车模块,该模块包含了添加商品、删除商品和修改商品数量等操作。
// javascriptcn.com 代码示例 // cart.js import goods from './goods.js'; const cart = { list: [], add(goodsName) { const goodsItem = goods.getGoodsList().find(goods => goods.name === goodsName); if (goodsItem) { const cartItem = this.list.find(goods => goods.name === goodsName); if (cartItem) { cartItem.quantity += 1; } else { this.list.push({ name: goodsItem.name, price: goodsItem.price, quantity: 1 }); } } }, remove(goodsName) { const index = this.list.findIndex(goods => goods.name === goodsName); if (index >= 0) { this.list.splice(index, 1); } }, update(goodsName, quantity) { const cartItem = this.list.find(goods => goods.name === goodsName); if (cartItem && quantity > 0) { cartItem.quantity = quantity; } }, getList() { return this.list; }, getTotal() { return this.list.reduce((prev, curr) => prev + curr.price * curr.quantity, 0); } }; export default cart;
在购物车模块中,我们使用 import
关键字引入了商品模块,然后定义了一个购物车对象,包含了添加商品、删除商品和修改商品数量等操作,最后将购物车对象定义为该模块的默认输出。
页面模块
最后,我们需要定义一个页面模块,该模块包含了展示购物车列表和操作按钮的功能。
// javascriptcn.com 代码示例 // page.js import cart from './cart.js'; function init() { const app = document.getElementById('app'); renderList(app); const addBtns = document.querySelectorAll('.add-btn'); const removeBtns = document.querySelectorAll('.remove-btn'); const updateBtns = document.querySelectorAll('.update-btn'); addBtns.forEach(btn => { btn.addEventListener('click', () => { cart.add(btn.dataset.name); renderList(app); }); }); removeBtns.forEach(btn => { btn.addEventListener('click', () => { cart.remove(btn.dataset.name); renderList(app); }); }); updateBtns.forEach(btn => { btn.addEventListener('click', () => { const quantity = parseInt(prompt(`请输入 ${btn.dataset.name} 的数量`, 0)); cart.update(btn.dataset.name, quantity); renderList(app); }); }); } function renderList(container) { container.innerHTML = ` <h2>购物车列表</h2> <table> <thead> <tr> <th>商品名称</th> <th>价格</th> <th>数量</th> <th>操作</th> </tr> </thead> <tbody> ${cart.getList().map(renderItem).join('')} </tbody> <tfoot> <tr> <td colspan="4">总价:${cart.getTotal()} 元</td> </tr> </tfoot> </table> `; } function renderItem(goodsItem) { return ` <tr> <td>${goodsItem.name}</td> <td>${goodsItem.price}</td> <td>${goodsItem.quantity}</td> <td> <button class="add-btn" data-name="${goodsItem.name}">添加</button> <button class="remove-btn" data-name="${goodsItem.name}">删除</button> <button class="update-btn" data-name="${goodsItem.name}">修改数量</button> </td> </tr> `; } export default { init };
在页面模块中,我们使用 import
关键字引入了购物车模块,然后定义了一个 init()
函数,用于初始化页面中的购物车列表和操作按钮。该函数会在页面加载后自动调用。
入口文件
最后,我们将把三个模块整合在一起,构建成一个完整的购物车页面。我们在入口文件中引入了页面模块,并在页面加载后调用了 init()
函数。
// main.js import page from './page.js'; window.addEventListener('DOMContentLoaded', () => { page.init(); });
总结
ES6 的模块化机制大大提高了代码的可维护性和可重用性,能够帮助我们更好地组织代码。在实际开发中,我们可以将代码按照业务功能划分为不同的模块,通过 export
和 import
关键字来实现模块之间的依赖关系。希望本文能够让大家更好地掌握 ES6 的模块化开发技能。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6538d4717d4982a6eb1f173a