Commonjs 模块化开发解析

起步

JavaScript 存在两种运行环境:

1. 浏览器工作环境

你可以有两种方法编辑 JS 代码。

  1. 其一,打开浏览器开发者工具,此处以 chrome 为例,启动浏览器窗口(键盘F5或者Ctrl + Shift + i),打开控制台(console)输入
var str = 'Hello World'; // 回车
str; // 回车, 输出"Hello World"
  1. 其二就是使用.html 文件,然后再浏览器开发者工具查看,因为不是我们今天要介绍的主要内容,这里就不再介绍啦。
<script>
  var obj = {
    name: '王勃',
    post: '落霞与孤鹜齐飞 秋水共长天一色',
  };
  console.log(obj);
</script>

2. nodejs 运行环境

你同样可以有两种方法编辑 JS 代码。以 VS Code 编辑器为例说明之

  1. 打开编辑器终端
node

node运行环境

在 node 运行环境输入

var str = {
  name: 'Andy',
  age: 12,
  gender: 'male',
};

node运行环境

  1. 利用 node 直接在编辑其运行, 在此我们建立如下项目结构以示说明

项目结构

在 inde.js 文件输入

console.log(1);

然后再 Terminal 终端运行,

node index.js

终端输出如下:

node运行环境3

如果我们修改文件,就需要重新执行上述 CLI 命令,开发十分不便,因此,我们有必要安装nodemon以便开发过程能够热更新运行结果;

  • nodemon全局安装
npm install -g nodemon
  • Linux 操作系统安装需要输入管理员权限
sudo npm install -g nodemon

现在再执行 index.js

nodemon运行index.js

Commonjs 项目介绍

现在让我们添加一段代码,看看 nodemon 的工作情况

nodemon运行

Commonjs 模块化开发思路

随着项目的发展,代码越来越长,不同的功能放在一个 JS 文件,既不便于开发,也不便于将来修改和删除维护,有没有方法将不同的功能放到不同的函数中,然后在不同的地方调用即可,答案是肯定的;

  1. 首先,让我们将 index.js 代码修改一下,用两个函数将两段功能代码进行封装,结果会是这样;

common初步

function demo() {
  console.log(1);
}
function person() {
  var str = {
    name: 'Andy',
    age: 12,
    gender: 'male',
  };
  console.log(str);
}

demo();
person();
  1. 现在开来还是存在问题,两段功能的代码始终是在 index.js 文件中,代码一多让人看看九就心烦,能否将这两段功能代码分别放到两个不同的 JS 文件中,仅仅在 index.js 中调用他们?答案是肯定的,你只要这样做
  • 创建两个 JS 文件,本案例分别创建 post.js 和 article.js

article.js

function demo() {
  console.log(1);
}

person.js

function person() {
  var str = {
    name: 'Andy',
    age: 12,
    gender: 'male',
  };
  console.log(str);
}
  • 现在怎样在 index.js 文件引入 article.js 和 post.js 呢?

index.js

const perosn = require('./js/person');

const article = require('./js/article');
  • 运行 nodemon,查看运行结果,nodemon 执行 index.js 或者 app.js 文件可以不需要输入文件名
nodemon   // === nodemon index.js

引入模块

如何在引入的文件使用被引入的文件呢?

  1. 此时,需要改造被引入文件 person.js 和 article.js,将需要被引用的模块暴露出去

article.js

function demo() {
  console.log(1);
}

module.exports = { demo };

person.js

function person() {
  var str = {
    name: 'Andy',
    age: 12,
    gender: 'male',
  };
  console.log(str);
}
module.exports = { person };
  1. 在引入文件 inde.js 调用文件
const person = require('./js/person');

const article = require('./js/article');

person.person();
article.demo();

运行结果如下

commonjs修改初步

  • 看看 index.js 这样调用是不是很麻烦,能否简便一些,你可以这样处理,将 person.js 的命名函数改为不匿名函数,就像这样。
module.exports = function () {
  var str = {
    name: 'Andy',
    age: 12,
    gender: 'male',
  };
  console.log(str);
};
  • index.js 调用
const person = require('./js/person');

const article = require('./js/article');

person();
article.demo();

怎样扩展被引入模块的功能

现在问题来啦,怎样扩展被引入模块的功能, 以 article.js 文件为例,我们需要扩展一个 post 功能模块,可以这样做

  1. 改造 article.js
function demo() {
  console.log(1);
}
function post(param) {
  console.log(param);
}
module.exports = { demo, post };
  1. index.js 调用, 在此案例我们传入的实参是一个配置对象,就像下边
article.post({
  name: '王勃',
  psot: '落霞与孤鹜齐飞 秋水共长天一色',
});
  • 参看运行结果

article改造

对引用文件的解构赋值

现在我们感觉对 article.js 的调用比较繁琐,能否对其进行简化,你可以采用 ES6 技术-对 demo 和 post 解构赋值

  • index.js
const person = require('./js/person');

const { demo, post } = require('./js/article');

person();
demo();
post({
  name: '王勃',
  psot: '落霞与孤鹜齐飞 秋水共长天一色',
});
  • 参看运行结果

解构赋值

exports 与 module.exports 的区别

为了说明这个问题,我们新创建一个文件 post.js,并将 article.js 文件复制过来

  • post.js
function demo() {
  console.log(1);
}
function post(param) {
  console.log(param);
}
module.exports = { demo, post };

现在我改造一下 post.js

exports.demo = function () {
  console.log(1);
};
exports.post = function (param) {
  console.log(param);
};
  • index.js 引入 post.js

为了便于调试,我们将 article.js 的引入给为 post.js 的引入

const person = require('./js/person');

const { demo, post } = require('./js/post');

person();
demo();
post({
  name: '王勃',
  psot: '落霞与孤鹜齐飞 秋水共长天一色',
});
  • 参看运行结果

exports

模块的类型

模块可以是任意 JS 规定的数据类型

  1. String 类型
  • string.js
exports.string = '渔舟唱晚 响穷彭蠡之滨 雁阵惊寒 声断衡阳之浦';
  • index.js 引入和调用
const { string } = require('./js/string.js');
console.log(string);
  • 参看运行结果

string

  1. Object 类型
  • object.js
exports.object = {
  sayHi: function (x) {
    return console.log(x);
  },
};
  • index.js 引入和调用
const { object } = require('./js/object.js');
object.sayHi({
  name: '屈原',
  post: '路漫漫其修远兮 吾将上下来求索',
});
  • 参看运行结果

object

模块的扩展

为了说明这问题,我们用一个案例来理解模块开发的扩展问题

项目分析
  1. 在开发过程中我们需要开发用户登录与注册功能

我们可以这样做,从 index.js => user.js => login.js 传入用户登录表单,然后在 login 功能模块与数据库传入的 email 进行查询,如果用户存在,允许登录,否者要求用户注册

我们也可以从 index.js => user.js => login.js 传入用户注册表单,然后在 login 功能模块与数据库传入的 email 进行查询,如果用户不存在,允许注册,否者要求用户更换注册名

  1. 登录、注册流程图

login流程图

  1. 首先创建/assets/js/login.js
exports.login = function (user) {
  console.log('login');
};
exports.registry = function (user) {
  console.log('registry');
};
  1. 创建/src/user.js
const { login, registry } = require('../assets/js/login');

module.exports = function (user) {
  login(user);
  registry(user);
};
  1. index.js 引入 user.js
const user = require('./js/user.js');

user();
  1. user.js 引入 login.js

  2. 测试

login

  1. 现在 index.js 传入 user 数据
const user = require('./js/user.js');

user({
  name: 'Andy',
  email: 'andy@gmail.com',
});
  1. login.js 登录功能

我们假设从数据库已经获得了 email 数据 => Email,是一个数组,模拟项目进程,使用 indexOf 方法,查找用户是否存在,indexOf 原本是用来查询字符串初次出现的位置,但是,也可以用来查询数组中是否存在某个数组元素,当数组元素存在时会显示其在数组中的下标;

以 login 函数为例

const Email = [
  'andy@gmail.com',
  'jhon@gmail.com',
  'jack@gmail.com',
  'andy@gmail.com',
  'alax@gmail.com',
];
exports.login = function (user) {
  const result = Email.indexOf(user.email);
  console.log(result);
};
exports.registry = function (user) {
  console.log(user.email);
};

参看结果

indexOf

'andy@gmail.com’的下标为 0,现在我们调换’andy@gmail.com’在数组中的位置,

参看结果

indexOf

'andy@gmail.com’的下标为 2,

  1. 判断 result>=0 时,返回 true,否则返回 flase

参看结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yStKfkGX-1618356062991)(https://z3.ax1x.com/2021/04/13/cyMvUe.png)]

  1. 修改 index.js 的 email,让数据在 Email 中不存在

参看结果

login = false

  1. registry 功能,可以类比 Login

login.js

const Email = [
  'jhon@gmail.com',
  'jack@gmail.com',
  'andy@gmail.com',
  'andy@gmail.com',
  'alax@gmail.com',
];
exports.login = function (user) {
  const result = Email.indexOf(user.email);
  if (result >= 0) return true;
  return '用户名不存在,请注册';
};
exports.registry = function (user) {
  const result = Email.indexOf(user.email);
  if (result < 0) return true;
  return '用户名已注册,请更换注册名!';
};

user.js

const { login, registry } = require('../assets/js/login');

module.exports = function (user) {
  let resultLogin = login(user);
  console.log(resultLogin);
  let resultRegistry = registry(user);
  console.log(resultRegistry);
};

参看结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pT5ibhj3-1618356062994)(https://z3.ax1x.com/2021/04/13/cy1SXt.png)]

  1. 测试

当 index.js 中 emial 存在时,返回的结果,可与上述结果相比较

index.js

const user = require('./js/user.js');

user({
  name: 'Andy',
  email: 'andy@gmail.com',
});

参看结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xUX7XAv0-1618356062996)(https://z3.ax1x.com/2021/04/13/cy1BND.png)]

总结

通过案例详细说明了使用模块化开发项目的全部过程。

源代码

源码下载地址commonjs 模块化开发相关源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值