JavaScript 代码导入与导出及 npm 使用指南
1. 利用导入和导出隔离功能
在 JavaScript 早期,所有代码都被放置在单个文件中,甚至开发者会将所有 JavaScript 代码放在 DOM 中的单个
<script>
标签下。后来,情况逐渐改善。有人创建了代码压缩和合并文件的工具,至少可以使用一个小的导入语句。接着,像 Require.js 和 CommonJS 这样的项目让开发者可以使用模块在文件间共享代码。如今,模块已简化为简单的导入和导出语句。
1.1 基本的导出和导入
最基本的,只需导出一个包含要共享数据的对象,这意味着可以导出函数、变量和类。也可以选择不导出某些内容,从而创建公共和私有函数。
示例代码如下:
// functions/context/method.js
const validator = {
message: 'is invalid.',
setInvalidMessage: field => `${field} ${this.message}`,
};
export { validator };
若要在另一个文件中使用该函数,使用
import
关键字和要导入的函数,并用花括号括起来,然后给出相对于当前文件的路径。
// architecture/import/single/bill.js
import { validator } from './context/method';
// 使用 validator
1.2 部分导出和导入
可以选择只导出部分函数,隐藏其他函数。
// architecture/import/single/util.js
function getPower(decimalPlaces) {
return 10 ** decimalPlaces;
}
function capitalize(word) {
return word[0].toUpperCase() + word.slice(1);
}
function roundToDecimalPlace(number, decimalPlaces = 2) {
const round = getPower(decimalPlaces);
return Math.round(number * round) / round;
}
export { capitalize, roundToDecimalPlace };
导入时,可以只导入需要的函数。
// architecture/import/single/name.js
import { capitalize } from './util';
function greet(name) {
return `Hello, ${capitalize(name)}!`;
}
greet('ashley');
// Hello, Ashley!
export { greet };
1.3 导出变量和类
除了函数,还可以导出变量和类。
// architecture/import/single/math.js
const PI = 3.14;
const E = 2.71828;
export { E, PI };
1.4 其他导入方式
可以将所有导入作为对象的属性,使用
*
导入所有函数并指定变量名。
// architecture/import/each/name.js
import * as utils from './util';
function greet(name) {
return `Hello, ${utils.capitalize(name)}!`;
}
greet('ashley');
// Hello, Ashley!
export { greet };
还可以重命名导入的函数或数据,使用
as
关键字。
1.5 快捷导出方式
可以在每个函数前添加
export
关键字,而不是在文件末尾声明对象。
// architecture/import/each/util.js
function getPower(decimalPlaces) {
return 10 ** decimalPlaces;
}
export function capitalize(word) {
return word[0].toUpperCase() + word.slice(1);
}
export function roundToDecimalPlace(number, decimalPlaces = 2) {
const round = getPower(decimalPlaces);
return Math.round(number * round) / round;
}
1.6 默认导出
当文件有单个入口点或某个函数更重要时,可以声明默认导出。
// architecture/import/default/address.js
import { capitalize } from '../single/util';
export function parseRegion(address) {
const region = address.state || address.providence || '';
return region.toUpperCase();
}
export function parseStreet({ street }) {
return street.split(' ')
.map(part => capitalize(part))
.join(' ');
}
export default function normalize(address) {
const street = parseStreet(address);
const city = address.city;
const region = parseRegion(address);
return `${street} ${city}, ${region}`;
}
导入默认导出时,不使用花括号。
// architecture/import/default/mail.js
import normalize from './address';
function getAddress(user) {
return normalize(user.address);
}
export default getAddress;
若要同时导入默认函数和其他函数,可以混合使用导入语句。
// architecture/import/default/list.js
import normalize, { parseRegion } from './address';
function getAddress(user) {
return normalize(user.address);
}
export function getAddressByRegion(users) {
return users.reduce((regions, user) => {
const { address } = user;
const region = parseRegion(address);
const addresses = regions[region] || [];
regions[region] = [...addresses, normalize(address)];
return regions;
}, {});
}
1.7 类的默认导出
默认导入在类上特别有用,因为每个文件通常只有一个类。
// architecture/import/class/address.js
import { capitalize } from '../single/util';
export default class Address {
constructor(address) {
this.address = address;
}
normalize() {
const street = this.parseStreet(this.address);
const city = this.address.city;
const region = this.parseRegion(this.address);
return `${street} ${city}, ${region}`;
}
parseStreet({ street }) {
return street.split(' ')
.map(part => capitalize(part))
.join(' ');
}
parseRegion(address) {
const region = address.state || address.providence || '';
return region.toUpperCase();
}
}
以下是导出和导入的流程图:
graph TD;
A[定义代码] --> B[导出代码];
B --> C[导入代码];
C --> D[使用代码];
1.8 总结
导入和导出非常直观,但随着项目增长,代码会分散在多个文件中。不过,这有助于更高效、逻辑地组织代码。
2. 使用 npm 利用社区知识
过去,如果想使用开源库,只能复制粘贴代码、下载库到项目或在标记中使用
<script>
标签包含外部依赖。现在,可以使用 Node 包管理器(npm)直接将代码下载到项目,控制版本,并使用熟悉的约定将代码导入到单个文件。
2.1 初始化项目
首先要安装 Node.js,安装时会同时安装 npm。安装完成后,打开终端,进入项目根目录,输入
npm init
初始化项目,这会启动一个配置工具,为你创建
package.json
文件。
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
2.2 评估开源代码
npm 不会在代码发布前进行审核,所以需要自己评估要包含在项目中的代码。评估步骤如下:
1.
下载量
:每月下载量多的代码可能更安全。
2.
问题数量
:问题多可能表示项目维护不佳,但大型项目可能因使用量大而有更多问题。
3.
查看代码库
:查看最新提交日期和拉取请求。如果代码在过去六个月内没有提交,可能已被弃用;如果有陈旧的合并请求,说明代码管理不佳。
4.
查看实际代码
:代码结构整洁、遵循标准约定通常更安全。
2.3 安装和使用开源库
以 Lodash 为例,若要将其安装到项目中,运行
npm install --save lodash
。该命令会创建
node_modules
目录,复制包,更新
package.json
文件以包含版本号,并创建
package-lock.json
文件。
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.4"
}
}
导入 Lodash 代码时,使用与之前相同的
import
命令,但无需给出路径。
// architecture/npm/utils/merge.js
import lodash, { fromPairs } from 'lodash';
export function mapToObject(map) {
return fromPairs([...map]);
}
export function objectToMap(object) {
const pairs = lodash.toPairs(object);
return new Map(pairs);
}
2.4 开发依赖
有时需要在代码库上工作但不包含在生产构建中的代码,如测试运行器。以 Prettier 为例,它是用于格式化代码的工具,安装时使用
npm install --save-dev prettier
。
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.4"
},
"devDependencies": {
"prettier": "^1.8.2"
}
}
若要使用 Prettier,可以使用 npm 脚本。在
package.json
的
scripts
字段中添加命令。
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"clean": "prettier --tab-width=4 --write ./code/*.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.4"
},
"devDependencies": {
"prettier": "^1.8.2"
}
}
在项目根目录下运行
npm run clean
即可执行该命令。
以下是使用 npm 的流程图:
graph TD;
A[安装 Node.js 和 npm] --> B[初始化项目 npm init];
B --> C[评估开源代码];
C --> D[安装开源库 npm install --save];
D --> E[安装开发依赖 npm install --save-dev];
E --> F[使用 npm 脚本运行命令];
2.5 总结
npm 对 JavaScript 开发非常有价值,查看新项目时,应先浏览
package.json
文件。有了组合多个文件和开源项目代码的工具后,接下来可以考虑如何组织代码。
3. 代码组织与管理
3.1 组件架构的引入
随着项目规模的扩大,代码文件数量增多,为了更好地组织和管理代码,引入组件架构是很有必要的。组件架构可以将相关的文件聚集在一起,使代码结构更加清晰,便于维护和扩展。
3.2 组件架构的优势
| 优势 | 描述 |
|---|---|
| 模块化 | 每个组件可以独立开发、测试和维护,提高开发效率。 |
| 可复用性 | 组件可以在不同的地方重复使用,减少代码冗余。 |
| 易于理解 | 代码结构清晰,团队成员可以更快地理解和上手项目。 |
3.3 组件架构示例
假设有一个电商项目,包含商品列表、购物车、用户信息等功能。可以将这些功能拆分成不同的组件,每个组件包含自己的 HTML、CSS 和 JavaScript 文件。
e-commerce-project/
├── components/
│ ├── product-list/
│ │ ├── product-list.html
│ │ ├── product-list.css
│ │ ├── product-list.js
│ ├── shopping-cart/
│ │ ├── shopping-cart.html
│ │ ├── shopping-cart.css
│ │ ├── shopping-cart.js
│ ├── user-info/
│ │ ├── user-info.html
│ │ ├── user-info.css
│ │ ├── user-info.js
├── index.html
├── main.css
├── main.js
3.4 组件之间的通信
组件之间可能需要进行数据传递和通信。可以使用事件、回调函数、状态管理库等方式来实现组件之间的通信。
以下是一个简单的事件通信示例:
// product-list.js
const productList = document.getElementById('product-list');
productList.addEventListener('product-selected', (event) => {
const selectedProduct = event.detail;
// 处理选中的商品
});
// 触发事件
const product = { id: 1, name: 'Product 1' };
const event = new CustomEvent('product-selected', { detail: product });
productList.dispatchEvent(event);
3.5 组件架构的流程图
graph TD;
A[项目根目录] --> B[组件目录];
B --> C[组件 1];
B --> D[组件 2];
B --> E[组件 3];
C --> F[HTML 文件];
C --> G[CSS 文件];
C --> H[JavaScript 文件];
D --> I[HTML 文件];
D --> J[CSS 文件];
D --> K[JavaScript 文件];
E --> L[HTML 文件];
E --> M[CSS 文件];
E --> N[JavaScript 文件];
4. 总结与建议
4.1 总结
通过使用导入和导出功能,可以在 JavaScript 文件之间共享代码,提高代码的复用性和可维护性。npm 作为一个强大的包管理工具,让我们可以轻松地下载和使用社区中的开源代码,同时还能管理项目的依赖和运行脚本。组件架构则帮助我们更好地组织和管理代码,使项目结构更加清晰。
4.2 建议
- 在编写代码时,尽量将功能模块化,使用导入和导出功能将代码分离到不同的文件中。
- 在选择开源库时,要仔细评估代码的质量和稳定性,避免引入有问题的代码。
- 合理使用组件架构,将相关的文件聚集在一起,提高代码的可维护性和可扩展性。
- 定期更新项目的依赖,确保使用的是最新版本的代码,以获取更好的性能和安全性。
希望这些内容能帮助你更好地进行 JavaScript 开发,提高代码质量和开发效率。
JavaScript模块化与npm应用
超级会员免费看
918

被折叠的 条评论
为什么被折叠?



