Node.js学习笔记
模块化
模块化基本概念
模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程,有多种属性,分别反映其内部特性。
编程领域的模块化,就是遵守固定的规则,把一个大文件拆成独立并且互相依赖的多个小模块
- 模块化拆分的好处
- 提高了代码的复用性
- 提高了代码的可维护性
- 可以实现按需加载
- Node.js中模块的分类
- 内置模块(如:fs、path、http)
- 自定义模块(用户创建的每个.js文件)
- 第三方模块(使用前需要先下载)
- 加载模块
使用require可以加载需要的内置模块、用户自定义模块以及第三方模块,在加载用户自定义模块期间,可以省略.js后缀名
Node.js中的模块化
- 什么是模块作用域
和函数作用域类似,在自定义模块中定义的变量、方法等方法,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域
- 模块作用域的好处
放置了全局变量污染的问题
我们创建一个06模块作用域.js
const username = '张三'
function sayHello(){
console.log('大家好,我是' + username)
}
09test.js
const custom = require('./06模块作用域')
console.log(custom)
在终端执行07test.js

- 向外共享模块作用域中的成员
在每个.js自定义模块中都有一个module对象, 它里面村粗了和当前模块有关的信息
打印module

module.export()
在自定义模块中,可以使用module.export()对象, 将模块内的成员共享出去,供外界使用,外界用require()方法导入自定义模块时,得到的就是module.export()所指的对象
08自定义模块.js
module.exports.username = '张三'
module.exports.sayHello = function(){
console.log('Hello!')
}
09test.js
const m = require('./08自定义模块')
console.log(m)
在终端执行09test.js,结果如图

exports
为了简化向外共享成员的代码,Node提供了exports对象,默认情况下,exports和module.exports指向同一个对象。最终共享的结果,还是以module.exports指向的对象为准。
- exports和module.exports的使用误区
require()模块时,得到的永远是module.exports指向的对象
-
CommonJs模块化规范
-
每个模块内部,module变量代表当前模块
-
module变量是一个对象,它的exports属性(即module.exports)是对外的接口
-
加载某个模块,其实是加载该模块的module.exports属性。require()方法用于加载模块化
npm与包
Node.js中的第三方模块又叫包。包是基于内置模块封装出来的,提供了更高级、更方便的API,极大的提高了开发效率。
https://www.npmjs.com/是全球最大的包共享平台,在这个网站上可以搜索自己需要的包
https://registry.npmjs.org/ 服务器上下载自己需要的包.
安装包
npm install <package-name>
通常会在此命令中看到更多标志:
--save安装并添加条目到package.json文件的 dependencies。--save-dev安装并添加条目到package.json文件的 devDependencies。也可以简写为-D
区别主要是,devDependencies 通常是开发的工具(例如测试的库),而 dependencies 则是与生产环境中的应用程序相关。
更新包
npm update <package-name>
卸载包
npm uninstall <package-name>
- npm格式化时间
传统做法的步骤
- 创建格式化时间的自定义模块
- 定义格式化时间的方法
- 创建补零函数
- 从自定义模块中到处格式化时间的函数
- 导入格式化时间的自定义模块
- 调用格式化时间的函数
具体实现:
10dateFormat.js
function dateFormat(dtStr){
const dt = new Date();
const y = dt.getFullYear();
const m = padZero(dt.getMonth() + 1);
const d = padZero(dt.getDate());
const hh = padZero(dt.getHours());
const mm = padZero(dt.getMinutes());
const ss = padZero(dt.getSeconds());
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
function padZero(n){
return n > 9? n : '0'+ n
}
module.exports = {
dateFormat
}
11test.js
const TIME = require('./10dateFormat')
const dt = new Date()
const newDT = TIME.dateFormat(dt)
console.log(newDT)

格式化时间的高级做法
具体步骤
- 使用npm包管理工具,在项目中安装格式化时间的包moment
- 使用require()导入格式化时间的包
- 参考moment的官方API文档对时间进行格式化
//导入需要的包
const moment = require('moment')
const dt = moment().format('YYYY-MM-DD HH:mm:ss')
console.log(dt)
- 使用npm的其他注意点
如果需要安装指定版本的包,可以在包名之后,通过**@符号**指定具体的版本
包的语义化版本规范
以点分十进制的形式进行定义,总共有三位数字。第一位数是大版本;第二位数是功能版本;第三位是Bug修复版本。版本号提升的规则:只要前面的版本号增长了,则后面的版本号归零。
- 包管理配置文件(package.json)
在项目根目录中,创建一个叫做package.json的配置文件,即可用来记录项目中安装了哪些包,从而方便剔除node_modules目录之后,在团队成员之间共享项目的源代码。可以运行npm install命令一次性安装所有的依赖包。
快速创建packag.json文件
npm init -y
注意:该命令只能在英文的目录下成功运行,所以项目文件夹的名称一定要用英文命名,不要使用中文,不能出现空格。
package.json文件中,dependencies节点,专门用来记录您使用npm install 命令安装了哪些包。如果某些包在开发和项目上线之后都需要用到,则建议把这些包记录到dependencies节点中。
devDependencies节点,如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议记录到devDependencies节点中。
卸载包 npm uninstall,这个操作会把卸载的包,自动从package.json的dependencies中移除掉
- 解决下包速度慢的问题
淘宝NPM镜像服务器
#查看当前的下包镜像源
npm config get registry
# 将下包的镜像源 切换为淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/
#检查镜像源是否下载成功
npm config get registry
为了方便的切换下包的镜像源,我们可以安装nrm这个小工具,利用nrm提供的终端命令,可以快速查看和切换下包的镜像源。
#将nrm安装为全局可用的攻击
npm i nrm -g
#查看所有可用的镜像源
nrm ls
#将下包的镜像源切换为taobao
nrm use taobao
- 包的分类
项目包:
-
开发依赖包(被记录到devDependencies节点中的包,只在开发期间会用到)
-
核心依赖包(被记录到dependencies节点中的包,在开发期间和项目上线之后都会用到)
全局包:(-g)
注意:
- 只有工具性质的包,才有全局安装的必要性,
- 判断某个包是否需要全局安装后才能使用,可以参考官方提供的使用说明即可
- i5ting_toc
可以把md文档转化成html页面的小工具
#将i5ting_toc安装为全局包
npm install -g i5ting_toc
#调用i5ting_toc,轻松实现md转html的功能
i5ting_toc -f xxx -o
(!!Typora可以导出成html文件)
- 规范的包的结构
- 包必须以单独的目录而存在
- 包的顶级目录下必须包含package.json这个包管理配置文件
- package.json中必须包含name ,version,main这三个属性,分别代表报的名字、版本号、包的入口
- 开发属于自己的包
需要实现的功能
- 格式化日期
- 转义HTML中的特殊字符
- 还原HTML中的特殊字符
将不同的功能进行模块化拆分
- 将格式化时间的功能,拆分到src->dateFormat.js中
- 将处理HTMLi字符串的功能,拆分到src->htmlEscape.js中
- 在index.js中,导入两个模块,得到需要 向外共享的方法
- 在index.js中,使用module.exports把对应的方法共享出去
//dateFormat.js
function dateFormat(dtStr) {
const dt = new Date();
const y = dt.getFullYear();
const m = padZero(dt.getMonth() + 1);
const d = padZero(dt.getDate());
const hh = padZero(dt.getHours());
const mm = padZero(dt.getMinutes());
const ss = padZero(dt.getSeconds());
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
function padZero(n) {
return n > 9 ? n : '0' + n
}
module.exports = {
dateFormat
}
//htmlEscape.js
//定义转义HTML字符的函数
function htmlEscape(htmlstr) {
return htmlstr.replace(/<|>|"|&/g, (match) => {
switch (match) {
case '<':
return '<';
case '>':
return '>';
case '"':
return '"';
case '&':
return '&';
}
})
}
// 定义还原 HTML 字符串的函数
function htmlUnEscape(str) {
return str.replace(/<|>|"|&/g, match => {
switch (match) {
case '<':
return '<'
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}
module.exports = {
htmlEscape,
htmlUnEscape
}
// index.js
const date = require('./src/dateFormat')
const escape = require('./src/htmlEscape')
// 向外暴露需要的成员
module.exports = {
...date,
...escape
}
//test.js
const mynpm = require('./index')
const htmlStr = `<h1 title="abc">这是h1标签<span>123 </span></h1>`
const str = mynpm.htmlEscape(htmlStr)
console.log(str)
console.log('------------')
const str2 = mynpm.htmlUnEscape(str)
console.log(str2)
console.log('------------')

模块的加载机制
优先从缓存中加载,这意味着多次调用require不会导致模块的代码被执行多次
- 内置模块的加载机制
加载优先级最高,例如require(‘fs’)始终返回内置的fs模块,即使在node_modules目录下有名字相同的包也叫做fs
- 自定义模块的加载机制
使用require加载自定义模块时,必须指定./或 …/开头的路径标识符,否则node会把它当作内置模块或第三方模块进行加载。
导入自定义模块时,如果省略了文件的扩展名,则Node.js会按顺序分别尝试加载以下的文件
- 按照确切的文件名进行加载
- 补全.js扩展名进行加载
- 补全.json扩展名进行加载
- 补全.node扩展名进行加载
- 加载失败,终端报错
- 第三方模块的加载机制
如果传递给 require的模块标识符不是一个内置模块,也没有以./或 …/开头,则Node.js会从当前模块的父目录开始,尝试从/node_modules文件夹中加载第三方模块。如果没有找到对应 的第三方模块,则一道道再上一层父目录中, 进行加载,知道文件系统的根目录。
- 目录作为模块
有三种加载方式
- 在被加载的目录下查找package.json文件,并寻找main属性, 作为require加载的入口
- 如果目录里没有package.json文件或main入口不存在或无法解析,则Node.js将会试图加载目录下的index.js文件
- 如果以上两步都失败了,则Node.js会在终端打印错误消息,报告模块的缺失: Error : Cannot find module ‘xxx’
本文详细介绍了Node.js的模块化概念,包括模块化的好处、Node.js中的内置和自定义模块、模块的加载机制。同时,文章讨论了npm(Node Package Manager)的基本用法,如安装、更新和卸载包,以及如何使用npm格式化日期。还提到了模块作用域、exports和module.exports的区别,并解释了package.json文件的重要性。

2170

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



