Commonjs 模块化开发解析
起步
JavaScript 存在两种运行环境:
1. 浏览器工作环境
你可以有两种方法编辑 JS 代码。
- 其一,打开浏览器开发者工具,此处以 chrome 为例,启动浏览器窗口(键盘
F5
或者Ctrl + Shift + i
),打开控制台(console)输入
var str = 'Hello World'; // 回车
str; // 回车, 输出"Hello World"
- 其二就是使用.html 文件,然后再浏览器开发者工具查看,因为不是我们今天要介绍的主要内容,这里就不再介绍啦。
<script>var obj = {name: '王勃',post: '落霞与孤鹜齐飞 秋水共长天一色',};console.log(obj);
</script>
2. nodejs 运行环境
你同样可以有两种方法编辑 JS 代码。以 VS Code 编辑器为例说明之
- 打开编辑器终端
node
在 node 运行环境输入
var str = {name: 'Andy',age: 12,gender: 'male',
};
- 利用 node 直接在编辑其运行, 在此我们建立如下项目结构以示说明
在 inde.js 文件输入
console.log(1);
然后再 Terminal 终端运行,
node index.js
终端输出如下:
如果我们修改文件,就需要重新执行上述 CLI 命令,开发十分不便,因此,我们有必要安装nodemon
以便开发过程能够热更新运行结果;
nodemon
全局安装
npm install -g nodemon
- Linux 操作系统安装需要输入管理员权限
sudo npm install -g nodemon
现在再执行 index.js
Commonjs 项目介绍
现在让我们添加一段代码,看看 nodemon 的工作情况
Commonjs 模块化开发思路
随着项目的发展,代码越来越长,不同的功能放在一个 JS 文件,既不便于开发,也不便于将来修改和删除维护,有没有方法将不同的功能放到不同的函数中,然后在不同的地方调用即可,答案是肯定的;
- 首先,让我们将 index.js 代码修改一下,用两个函数将两段功能代码进行封装,结果会是这样;
function demo() {console.log(1);
}
function person() {var str = {name: 'Andy',age: 12,gender: 'male',};console.log(str);
}demo();
person();
- 现在开来还是存在问题,两段功能的代码始终是在 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
如何在引入的文件使用被引入的文件呢?
- 此时,需要改造被引入文件 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 };
- 在引入文件 inde.js 调用文件
const person = require('./js/person');const article = require('./js/article');person.person();
article.demo();
运行结果如下
- 看看 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 功能模块,可以这样做
- 改造 article.js
function demo() {console.log(1);
}
function post(param) {console.log(param);
}
module.exports = { demo, post };
- index.js 调用, 在此案例我们传入的实参是一个配置对象,就像下边
article.post({name: '王勃',psot: '落霞与孤鹜齐飞 秋水共长天一色',
});
- 参看运行结果
对引用文件的解构赋值
现在我们感觉对 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: '落霞与孤鹜齐飞 秋水共长天一色',
});
- 参看运行结果
模块的类型
模块可以是任意 JS 规定的数据类型
- String 类型
- string.js
exports.string = '渔舟唱晚 响穷彭蠡之滨 雁阵惊寒 声断衡阳之浦';
- index.js 引入和调用
const { string } = require('./js/string.js');
console.log(string);
- 参看运行结果
- Object 类型
- object.js
exports.object = {sayHi: function (x) {return console.log(x);},
};
- index.js 引入和调用
const { object } = require('./js/object.js');
object.sayHi({name: '屈原',post: '路漫漫其修远兮 吾将上下来求索',
});
- 参看运行结果
模块的扩展
为了说明这问题,我们用一个案例来理解模块开发的扩展问题
项目分析
- 在开发过程中我们需要开发用户登录与注册功能
我们可以这样做,从 index.js => user.js => login.js 传入用户登录表单,然后在 login 功能模块与数据库传入的 email 进行查询,如果用户存在,允许登录,否者要求用户注册
我们也可以从 index.js => user.js => login.js 传入用户注册表单,然后在 login 功能模块与数据库传入的 email 进行查询,如果用户不存在,允许注册,否者要求用户更换注册名
- 登录、注册流程图
- 首先创建/assets/js/login.js
exports.login = function (user) {console.log('login');
};
exports.registry = function (user) {console.log('registry');
};
- 创建/src/user.js
const { login, registry } = require('../assets/js/login');module.exports = function (user) {login(user);registry(user);
};
- index.js 引入 user.js
const user = require('./js/user.js');user();
user.js 引入 login.js
测试
- 现在 index.js 传入 user 数据
const user = require('./js/user.js');user({name: 'Andy',email: 'andy@gmail.com',
});
- 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);
};
参看结果
'andy@gmail.com’的下标为 0,现在我们调换’andy@gmail.com’在数组中的位置,
参看结果
'andy@gmail.com’的下标为 2,
- 判断 result>=0 时,返回 true,否则返回 flase
参看结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yStKfkGX-1618356062991)(https://z3.ax1x.com/2021/04/13/cyMvUe.png)]
- 修改 index.js 的 email,让数据在 Email 中不存在
参看结果
- 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)]
- 测试
当 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 模块化开发相关源码
Commonjs 模块化开发解析相关推荐
- 前端面试题 ~ 有关模块化开发
1.说说你对前端模块化开发的认识. (1)异步模块定义(AMD)规范是 require. js推广的.对模块定义的规范. (2)通用模块定义(CMD)规范是 SeaJS推广的.对模块定义的规范. (3 ...
- js 多个定时器_Node.js系列深入浅出Node模块化开发——CommonJS规范
前言 本文将为大家透彻的介绍关于Node的模块化--CommonJS的一切. 看完本文可以掌握,以下几个方面: 什么是模块化,以及没有模块化会带来哪些问题,是如何解决的: JavaScript的设计缺 ...
- 模块化开发:AMD、CMD、CommonJs和Es6的区别
什么是AMD.CMD.CommonJs? 他们之间有什么区别? 项目当中都是如何运用的? AMD即Asynchronous Module Definition,是RequireJS在推广过程中对模块定 ...
- 五、Vue模块化开发学习笔记——JavaScript原始功能、匿名函数的解决方案、使用模块作为出口、CommonJS、ES6 export和import的使用
一.JavaScript原始功能 -在网页开发的早期,js制作作为一种脚本语言,做一些简单的表单验证或动画实现等,那个时候代码还是很少的. 那个时候的代码是怎么写的呢? 直接将代码写在<scri ...
- SOFABoot源码解析之模块化开发
1.SOFABoot源码解析 1.1模块化开发 1.1.1 简述 关于SOFABoot模块化开发的文档来自于Alipay开源社区Wiki,链接地址为: https://github.com/alipa ...
- commonjs 和 es6模块化开发入门
commonjs模块化 首先写一个api,提供给外部调用 //commonjslet sum =(a,b)=> a+b;// 暴露接口 module.exports = {sum // sum: ...
- JavaScript模块化开发技术概述
2019独角兽企业重金招聘Python工程师标准>>> 什么是模块化开发? 前端开发中,起初只要在script标签中嵌入几十上百行代码就能实现一些基本的交互效果,后来js得到重视,应 ...
- 前端模块化开发学习之gulpbrowserify篇
随着web应用的发展,前端的比重占得越来越多,编写代码从而也越来越复杂.而通常我们需要将不同功能或者不同模块的代码分开写,最后在html中一起加载,这样做是可以的,但是当你需要进行维护或者是二次开发 ...
- Js模块化开发的理解
Js模块化开发的理解 模块化是一个语言发展的必经之路,其能够帮助开发者拆分和组织代码,随着前端技术的发展,前端编写的代码量也越来越大,就需要对代码有很好的管理,而模块化能够帮助开发者解决命名冲突.管理 ...
最新文章
- STL vector
- 一个基于POI的通用excel导入导出工具类的简单实现及使用方法
- matlab作图如何改变坐标刻度
- python删除第一行_Python删除文件第一行
- Spring声明式事务示例
- Python Dataframe转List
- Java查询图书信息
- python 爬虫应用
- EF架构~DefaultValue让我的UnitOfWork更可读
- 机械设计参考CAD零件图纸常用素材资料(300张)
- ssm+vue基于微信小程序的数学辅导教学学习系统#毕业设计
- android app 设置以太网静态Ip
- 腾讯云快速增长背后 三大短板仍需补足
- Cadence OrCad Capture新建工程的方法
- win10下的linux占用大小,详解Win10系统上使用Linux之前要知道的几件事
- 编译原理_P1004
- 使用myeclispe或者sts工具,创建的myBatis的 xml文件不提示的问题解决方法
- oracle 英文简写的日期转成数值型日期的字符串
- 2022年嵌入式开发就业前景怎么样?
- iphone12android在线啥意思,iPhone12的新功能 你的安卓手机早就已经有了