• 核心模块
    • fs 文件操作模块
    • http 网络服务构建模块
    • os 操作系统信息模块
    • path 路径处理模块
  • 用户自定义模块
    • 通过require(‘路径’) 加载模块,例如:require(‘./b.js’), 相对路径 ./ 不能省略
    • 可以省略文件后缀名,默认 .js
  • 第三方模块
    • art-template
    • 必须通过 npm 来下载才可以使用

CommonJS 模块规范

  • 模块作用域(模块是独立的,在不同的文件使用必须要重新引用)
  • 使用 require 方法来加载模块
  • 使用 exports 接口对象来导出模板中的成员

加载(require)

语法:

  1. var 自定义变量名 = require('模块')

作用:

  • 执行被加载模块中的代码
  • 得到被加载模块中的 exports 导出接口对象

导出(exports)

  • Node 中是模块作用域,默认文件中所有的成员只在当前模块有效
  • 对于希望可以被其他模块访问到的成员,我们需要把这些公开的成员都挂载到 exports 接口对象中就可以了

导出多个成员(必须在对象中,exports 是一个对象):

  1. exports.a = 123;
  2. exports.b = 'hello';
  3. exports.c = function(){
  4. console.log('bbb')
  5. };
  6. exports.d = {
  7. foo:"bar"
  8. };

导出单个成员:

  1. module.exports = 'hello';
  2. // 后者会覆盖前者
  3. module.exports = function add(x,y) {
  4. return x+y;
  5. }

也可以通过以下方法来导出多个成员:

  1. module.exports = {
  2. foo: 'hello',
  3. add:function(){
  4. return x+y;
  5. }
  6. };

原理

在 node 中,每个模块内部都有一个自已的 module 对象

在 module 对象中,有一个成员 exports(也是一个对象)

  1. module = {
  2. exports = {
  3. }
  4. }

即可以通过 module.exports 也可以通过 exports 导出,因为 exportsmodule.exports 的一个引用:

  1. console.log(exports === module.exports); // true
  2. exports.foo = 'bar';
  3. //等价于
  4. module.exports.foo = 'bar';

当给 exports 重新赋值后, exports != module.exports
可以通过 exports == module.exports 用来重新建立关系

最终 return 的是 module.exports,无论 exports 中的成员是什么都没用

真正去使用的时候:

  • 导出单个成员: module.exports = xxx;
  • 导出多个成员: module.exports.xxx 或者 module.exports = {};

require方法加载规则

  • 优先从缓存加载(不会重复加载)
  • 判断模块标识符
    • 核心模块(模块名)
    • 用户自定义模块(以路径形式加载)
    • 第三方模块
      • 先找到当前文件所处目录中的 node_modules 目录
      • node_modules/art-template(模块名)
      • node_modules/art-template/package.json 文件
      • node_modules/art-template/package.json 文件中的 main 属性
      • main 属性中就记录了 art-template 的入口模块
      • 然后加载使用这个第三方包
      • 如果 package.json 文件不存在或者 main 指定的入口模块也没有
      • 则 node 会默认找该目录下的 Index.js
      • 如果以上任何一个条件都不成立,则会进入上一级目录按以上规则查找
      • 直到磁盘根目录,最后报错

核心模块使用

文件的读写

  1. // 1.使用fs核心模块
  2. var fs = require('fs');
  3. // 2.读取文件
  4. // 第一个参数就是要读取的文件路径
  5. // 第二个参数是一个回调函数
  6. // 成功
  7. // data 数据
  8. // err null
  9. // 失败
  10. // data undefined 没有数据
  11. // err 错误对象
  12. fs.readFile('./data/a.txt',function(err,data){
  13. if(err){
  14. console.log('文件读取失败');
  15. }else{
  16. // 文件中存储的都是二进制数据
  17. // 通过toString()方法转换为我们能认识的字符
  18. // 可以结合服务器通过读取文件来实现发送页面
  19. console.log(data.toString());
  20. }
  21. })
  22. // 3.将数据写入文件
  23. // 第一个参数:文件路径
  24. // 第二个参数:文件内容
  25. // 第三个参数:回调函数
  26. fs.writeFile('./data/a.txt','写入文件的内容',function(err){
  27. if(err){
  28. console.log('写入失败');
  29. }
  30. else{
  31. console.log('写入成功');
  32. }
  33. })

HTTP 服务

  • 提供服务:对数据服务
  • 发送请求
  • 接收请求
  • 处理请求
  • 反馈(发送响应)
  • 当客户端请求过来,就会自动触发服务器的 request 请求事件,然后执行第二个参数:回调处理函数
// 1.加载http核心模块 
var http = require('http'); 
var fs = require('fs'); 
// 2.使用http.createServer()创建一个web服务器 
var server = http.createServer(); 
// 读取文件时的根目录 
var wwwDir = 'D:/app/www' 
// 3.触发服务器的request请求事件 
//     request 请求事件处理函数,需要接收两个参数: 
//         request 请求对象 
//             请求对象可以用来获取客户端的一些请求信息,例如请求地址 
//         response 响应对象 
//             响应对象可以用来给客户端发送响应消息 
server.on('request', function (req, res) { 
    // 获取当前 url(端口号后面的路径) 
    var url = req.url 
    // 默认为 /index.html 
    var filePath = '/index.html' 
    // 如果不是默认 url,则获取当前用户输入的 url 
    if (url !== '/') { 
        filePath = url 
    } 
    // 读取文件 
    fs.readFile(wwwDir + filePath, function (err, data) { 
        if (err) { 
            // 响应内容只能是字符串或二进制数据 
            // 告诉浏览器发送的是什么类型的内容 
            // 图片不需要指定编码 
            response.setHeader('Content-Type', 'text/html; charset=utf-8') 
            return res.end('404 NOT Found') 
        } 
        res.end(data) 
    }) 
}) 
// 4.绑定端口号,启动服务 
server.listen(3000, function () { 
    console.log('running') 
})

path 路径操作模块

参考文档: https://nodejs.org/dist/latest-v14.x/docs/api/path.html

  • path.basename:获取路径的文件名,默认包含扩展名
    • 第二个参数传一个文件扩展名获取到的文件名就不包含扩展名
  • path.dirname:获取路径中的目录部分
  • path.extname:获取一个路径中的扩展名部分
  • path.isAbsolute:判断一个路径是否为绝对路径
  • path.parse:把路径转换为对象
    • root:根路径
    • dir:目录
    • base:包含扩展名的文件名
    • ext:扩展名
    • name:不包含扩展名的文件名
  • path.join:拼接路径

Node中的其它成员

在每个模块中,除了 require , exports 等模块相关的 API 之外,还有两个特殊的成员:

  • __dirname ,可以用来 动态 获取当前文件模块所属目录的绝对路径(不包含文件名)
  • __filename ,可以用来 动态 获取当前文件的绝对路径(包含文件名)
  • __dirnamefilename 是不受执行 node 命令所属路径影响的

在文件操作中,使用相对路径是不可靠的,因为 node 中文件操作的路径被设计为相对于执行 node 命令所处的终端路径。

所以为了解决这个问题,只需要把相对路径变为绝对路径(绝对路径不受任何影响)就可以了。

就可以使用 __dirname 或者 __filename 来帮助我们解决这个问题

在拼接路径的过程中,为了避免手动拼接带来的一些低级错误,推荐使用 path.join() 来辅助拼接

模块中的路径标识和这里的路径没关系,不受 node 命令执行所处目录影响(相对于文件模块)

var fs = require('fs'); 
var path = require('path'); 
// console.log(__dirname + 'a.txt'); 
// path.join方法会将文件操作中的相对路径都统一的转为动态的绝对路径 
fs.readFile(path.join(__dirname + '/a.txt'),'utf8',function(err,data){ 
if(err){ 
throw err 
} 
console.log(data); 
});

补充:模块中的路径标识和这里的路径没关系,不受影响(就是相对于文件模块) 注意: 模块中的路径标识和文件操作中的相对路径标识不一致 模块中的路径标识就是相对于当前文件模块,不受node命令所处路径影响