Node.js学习第三天
1.模块化
1.1 模块化的定义
- 模块化指解决一个复杂问题时,自顶向下逐层把系统划分为若干模块的过程。对应整个系统来说,模块是可组合、分解、更换的单元
1.2 编程领域的模块化
- 遵守固定的规则,把一个大文件拆分成独立并相互依赖的多个小模块
- 好处
- 提高了代码的复用性
- 提供了代码的可维护性
- 可以实现按需加载
1.3 模块化的规范
- 对代码进行模块化的拆分和组合时,需要遵守的那些规则
- 使用什么样的语法格式来引用模块
- 在模块中使用什么样的语法格式向外暴露成员
2.Node.js中的模块化
2.1 Node.js中模块的分类
- 内置模块:Node.js官方提供,如fs,path,http
- 自定义模块:用户创建的每个.js文件
- 第三方模块:由第三方开发出来的模块,并非官方提供,也不是用户创建的自定义模块,使用前需要下载
2.2 加载模块
- 使用require()方法,可以加载需要的内置模块,用户自定义模块,第三方模块
| |
| const fs = require('fs') |
| |
| |
| |
| const zdy = require('./zdy.js') |
| |
| |
| |
| const moment=require('moment') |
示例
| const zdy = require('./02.zdy.js') |
| |
| console.log(zdy); |

注意点
| const zdy = require('./02.zdy') |
| |
| console.log(zdy); |
2.3 模块作用域
- 和函数作用域类似,在自定义模块中定义的变量、方法,只能在当前模块内被访问
- 图解

-
好处

示例
| console.log("自定义模块被加载"); |
| |
| const ename = '张三'; |
| const zdy = require('./02.zdy.js') |
| |
| console.log(zdy); |

2.4 向外共享模块作用域中的成员
2.4.1 module对象
- 每个.js自定义模块中都有一个module对象,里面存储了和当前模块有关的信息
示例

2.4.2 module.exports对象
- 在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用
- 使用require()方法导入自定义模块时,得到的就是module.exports所指向的对象
示例
| |
| |
| module.exports.username = 'zs'; |
| |
| |
| |
| module.exports.sayHello = function() { |
| console.log("hello!"); |
| } |
| |
| const age = 20; |
| module.exports.age = age; |
| const zdy = require('./06.自定义模块') |
| |
| console.log(zdy); |

2.4.3 共享成员时的注意点
- 使用require()方法导入模块时,导入的结果,永远以module.exports指向的对象为准
示例
| |
| |
| module.exports.username = 'zd'; |
| |
| module.exports.sayHello = function() { |
| console.log("hello"); |
| } |
| |
| |
| |
| module.exports = { |
| ename: 'k', |
| eage: '18', |
| sayHi() { |
| console.log("Hi"); |
| } |
| } |
| const zdy2 = require('./08.自定义模块2') |
| |
| console.log(zdy2); |

2.4.4 exports对象
| console.log(exports); |
| console.log(module.exports); |
| |
| console.log(exports === module.exports); |

示例
| module.exports.age = '19' |
| exports.username = 'zs' |
| exports.age = '18' |
| exports.sayHello = function() { |
| console.log("Hello"); |
| } |
| const zdy3 = require('./11.自定义模块3') |
| |
| console.log(zdy3); |

2.4.5 exports 和module.exports的使用误区
- 得到的永远是module.exports指向的对象
- 为了防止混乱,不要同时使用exports和module.exports




2.4.6 Node.js中的模块化规范
- 遵循CommonJs模块化规范
- CommonJs规定
- 每个模块内部,module变量代表当前模块
- module变量是一个对象,他的exports属性(即module.exports)是对外的接口
- 加载某个模块,其实就是加载该模块的module.exports属性,require()方法用于加载模块
3.npm和包
3.1 包
- Node.js中的第三方模块叫做包
- 包由第三方个人或团队开发出来的
- Node.js的包免费开源
3.2 包的作用
- Node.js的内置模块仅仅提供了一些底层的API,包是基于内置模块封装出来的,提高了开发效率
- 包与内置模块的关系,类似与jQuery和浏览器内置API之间的关系
3.3 包的下载
3.4 moment包的使用
| function dateFormat(dt) { |
| |
| |
| var y = dt.getFullYear(); |
| var m = padZero(dt.getMonth() + 1); |
| var d = padZero(dt.getDate()); |
| |
| var h = padZero(dt.getHours()); |
| |
| var mm = padZero(dt.getMinutes()); |
| var s = padZero(dt.getSeconds()); |
| |
| return `${y}-${m}-${d} ${h}:${mm}:${s}` |
| |
| } |
| |
| |
| |
| function padZero(n) { |
| return n < 10 ? '0' + n : n; |
| } |
| |
| module.exports = { |
| dateFormat |
| } |
| var format = require('./14.自定义日期格式化') |
| |
| var date = new Date(); |
| |
| var str = format.dateFormat(date); |
| |
| console.log(str); |

直接使用moment包来格式化日期
- 下载包(管理员身份运行,先进入项目所在目录,再下载)
<Moment.js | Docs (momentjs.com)>
| |
| const mt = require("moment") |
| |
| var dt = mt().format("YYYY-MM-DD HH:mm:ss"); |
| |
| console.log(dt); |

3.4 装包后多的文件
- node_modules文件夹和package-lock.json的配置文件
- node_modules用来存放已安装到项目中的包,require()导入第三方包时,从这个目录查找并加载包
- package-lock.json:记录每一个包下的下载信息,例如包名,版本号等
3.5 包的版本号
3.6 包管理配置文件
- npm规定:在项目根目录中,必须提供一个叫做package.json的包管理配置文件,记录相关信息
- 项目的名称,版本号,描述
- 项目中都用到了哪些包
- 哪些包只在开发期间会用到
- 哪些包在开发和部署阶段都需要用到


-
package.json配置文件
- 注意点
- 只能在英文的目录下成功运行,不能使用中午,不能使用空格
- 创建成功后,提高npm install 命令安装包时,npm包管理工具会自动的把包的名称和版本号,记录到package.json中
-
dependencies 节点
- package.json 配置文件中的节点
- 专门记录安装了哪些包

-
同时安装多个包,包名之间用空格隔开
| npm i jquery art-template |
- 一次性安装所有的依赖包(存在package.json配置文件)
| // 执行npm install 或 npm i 命令时,npm包管理工具会读取package.json 中的dependencies 节点 |
| // 读取节点中的包名称和版本号后,就会把这些包一次性全部下载 |
| |
| npm install |
- 卸载包
- 卸载包之后,package.json的dependencies节点的相关记录也会删除
3.7 解决下包慢的问题

| # 查看当前的下包镜像源 |
| npm config get registry |
| # 将下包镜像源切换为淘宝镜像源 |
| npm config set registry=https://registry.npmmirror.com/ |
| # 检查镜像源是否切换成功 |
| npm config get registry |
3.8 nrm
- 一个工具,方便切换下包的镜像源,快速查看和切换下包的镜像源
| # 提高 npm包管理器,安装nrm为全局可用的工具 |
| npm i nrm -g |
| # 查看可用的镜像源 |
| nrm ls |
| # 将下包的镜像源切换为淘宝 |
| nrm use taobao |
3.9 包的分类
3.10 i5ting_toc
| # 将i5ting_toc 安装为全局包 |
| npm install i5ting_toc -g |
| |
| #调用i5ting_toc 实现md转html的功能 |
| |
| i5ting_toc -f 要转换的md文件路径 -o |
3.11 规范的包结构
- 包必须以单独的目录存在
- 包的顶级目录下包含package.json这个包管理配置文件
- package.json包含name,version,main三个属性,代表包名,包版本,包的入口(js文件所在)
4.开发自己的包
- 包实现的功能
- 格式化日期
- 转义html特殊字符
- html字符还原
- 初始化包的基本结构
- 新建day03-utils文件夹,作为包的根目录
- 在day03-utils文件夹中新建三个文件
- index.js
- package.json(可使用npm init -y) 来自动创建,再修改一下
- README.md说明文档
- 包的功能的模块化
- 根目录下创建src文件夹
- 将格式化日期的功能拆分到src--->dateDateFormat.js中
- 处理html的字符串拆分到src->htmlTo
- index.js导入上述两个功能,在把功能暴露出去
- package.json
| { |
| "name": "day03-utils", |
| "version": "1.0.0", |
| "description": "用于html的转换,时间日期格式化", |
| "main": "index.js", |
| "scripts": { |
| "test": "echo \"Error: no test specified\" && exit 1" |
| }, |
| "keywords": ["lingxin", "html", "Formdate"], |
| "author": "lingxin", |
| |
| "license": "ISC" |
| } |
| |
| |
| |
| |
| const date = require('./src/dateFormat'); |
| const htmlTo = require('./src/htmlTo') |
| |
| |
| |
| module.exports = { |
| |
| ...date, |
| ...htmlTo |
| } |
| |
| function dateFormat(dateStr) { |
| var date = new Date(dateStr); |
| var y = date.getFullYear(); |
| var m = padZero(date.getMonth() + 1); |
| var d = padZero(date.getDate()); |
| var h = padZero(date.getHours()); |
| var mm = padZero(date.getMinutes()); |
| var ss = padZero(date.getSeconds()); |
| |
| return `${y}-${m}-${d}-${h}-${mm}-${ss}` |
| } |
| |
| |
| |
| function padZero(n) { |
| return n < 10 ? '0' + n : n; |
| } |
| |
| module.exports = { |
| dateFormat |
| } |
| |
| |
| function htmlToEntity(htmlStr) { |
| return htmlStr.replace(/<|>|"|&/g, function(match) { |
| switch (match) { |
| case '<': |
| return '<' |
| case '>': |
| return '>' |
| case '"': |
| return '"' |
| case '&': |
| return '&' |
| } |
| }) |
| } |
| |
| |
| function htmlTochar(htmlStr) { |
| return htmlStr.replace(/<|>|&|"/g, function(match) { |
| switch (match) { |
| case '<': |
| return '<' |
| case '>': |
| return '>' |
| case '&': |
| return '&' |
| case '"': |
| return '"' |
| } |
| }) |
| } |
| |
| module.exports = { |
| htmlToEntity, |
| htmlTochar |
| } |
| ## 安装 |
| ```shell |
| npm install day03-utils |
| ``` |
| |
| ## 导入 |
| |
| ```js |
| const d3 = require('day03-utils'); |
| ``` |
| |
| ## 格式化日期函数的使用 |
| ```js |
| var time = d3.dateFormat(new Date()); |
| console.log(time); |
| // 输出结果 2022-03-14-18-53-18 |
| ``` |
| ## 转义特殊字符的使用 |
| ```js |
| // 测试字符转义 |
| var str2 = d3.htmlToEntity(str); |
| console.log(str2); |
| // 输出结果:<h1 title="666">123&nbsp;<h1/> |
| ``` |
| |
| ## 还原特殊字符的使用 |
| ```js |
| |
| var str2 = d3.htmlToEntity(str); |
| // 测试字符还原 |
| var str3 = d3.htmlTochar(str2); |
| console.log(str3); |
| // 输出结果:<h1 title="666">123 <h1/> |
| ``` |
| ## 开源协议 |
| |
| ISC |
5.发布包到npm上
-
注册npm的账号
-
在终端上登录npm账户
- 首先将下包的服务器切换成npm的官方服务器
- 使用nrm工具换源
- 终端登录

-
发布包到npm
- 将终端切换到根目录下
- 在npm官网中查看包名是否雷同(雷同不能发布)
- 输入发包命令
-
删除已发布的包

6. 模块加载机制
6.1 模块优先从缓存中加载
- 模块在第一次被加载时里面的代码会被执行,加载后模块被缓存,多次调用require()方法不会导致模块的代表被多次执行
示例
| require('./17.自定义模块4') |
| |
| |
| require('./17.自定义模块4') |
| |
| require('./17.自定义模块4') |

6.2 内置模块的加载机制
- 内置模块是由Node.js官方提供的,内置模块的加载优先级最高
- 例如,require('fs')始终返回内置的fs模块,即使在node_modules目录下有名字相同的包也叫做fs
6.3 自定义模块的加载机制
- 使用require()加载自定义模块时,必须指定以./或../开头的路径标识符,在加载自定义模块时,如果没有指定./或../这样的路径标识符,则node会把他当作内置模块或第三方模块进行加载

6.4 第三方模块的加载机制

6.5 目录作为模块

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!