1、node.js中模块的分类

  1)node.js内置模块(核心,原生)

    所有内置模块在安装node.js时就已经编译成二进制文件,可以直接加载运行(速度较快),部分内置模块,在node.exe这个进程启动时就已经默认加载了,可以直接使用。

  2)文件模块

    require(./common.js); // 去当前js文件的路径下找commom.js文件并导入执行。如果导入时没有指定文件后缀require(./commom),那么就按照commom.js,common.json,commom.node(c/c++编写)去找对应的文件。没有找到对应的文件,就去找common文件夹,如果找到了,看common文件夹里面有没有package.json文件,package.json文件有没有定义入口(main)。

  3)自定义模块(第三方模块)比如mime

    首先会在项目根目录下的node_modules文件夹里面找对应模块,没有找到去上一级目录找,直到盘符目录。

2、require加载模块注意

  1)所有模块第一次加载完毕后都会有缓存,后面加载就直接读取缓存,避免了二次开销。因为有缓存,所以模块加载只会执行一次。

  2)每次加载优先从缓存中加载,没有才按照node.js加载模块的规则去查找

  3)核心模块在node.js源码编译的时候,都已经编译为二进制执行文件,所以加载速度较快(核心模块的优先级仅次于缓存)

  4)核心模块保存在lib目录下

  5)试图加载一个和核心模块同名的自定义模块是不会成功的,只能使用路径的方式加载。

  6)核心模块只能通过模块名称来加载,不可以通过路径加载

  7)require(./common.js)中"./"相对路径是相对当前模块(或当前js文件)

  8)建议加载文件模块时,文件后缀不要省略

3、CommonJS规范

  CommonJS规范是为js语言制定的一种模块规范、编程API规范。

  node.js遵循了CommonJS规范

4、module.exports介绍(两个模块进行通信,如何使用加载的模块)

  需求:如何在index.js加载a.js模块,并且使用a.js模块中的数据和方法

  第一步:首先新建文件夹node-module-demo

  第二步:在node-module-demo目录新建index.js文件

  第三步:npm init -y

  第四步:a.js和index.js

  a.js

var a = {
name: '张三',
id: 20,
add: function(x, y) {
return x + y;
}
};
module.exports = a;

  index.js

var a = require('./a.js');
var result = a.add(10, 20);
console.log(result); //
console.log(a.name); // 张三
console.log(a.id); //

  

  事实上,如果a.js不指定module.exports,默认返回一个对象。

// a.js代码:
module.exports.name = "李四";
module.exports.id = 10;
module.exports.sayHi = function () {
console.log('hello您好');
}; // index.js代码:
var a = require('./a.js');
a.sayHi();
console.log(a.name);
console.log(a.id);

5、exports和module.exports的区别
  1)exprots和module.exports指向的是同一个对象
  2)最终require()函数返回的是module.exports中的数据

  const exports = module.exports;

  所以,不要重新给exports指定,比如像下面代码,就将exports的指向变了:

exports = {
a: 1
};

6、将上一篇博客的Demo进行模块化改造
  1)模块化:便于多人合作、便于后期维护
  2)模块化思路:将Demo分成以下模块
          - 服务模块:负责启动服务  app.js
          - 扩展模块:扩展req和res对象  context.js
          - 路由模块:负责路由判断  router.js
          - 业务模块:负责处理具体路由的业务  handler.js
          - 数据操作模块:负责进行数据库操作
          - 配置模块:保存配置信息

  app.js

// 加载http模块
var http = require("http"); var context = require("./context.js");
var router = require("./router.js");
var config = require('./config.js'); // 创建一个http服务对象
http.createServer(function(req, res) { context(req, res);
router(req, res); }).listen(config.port, function() {
console.log('服务器已经启动,请访问http://127.0.0.1:' + config.port);
});

  context.js

// context模块作用:扩展req和res对象
var url = require("url");
var fs = require("fs");
var mime = require("mime");
var _ = require("underscore"); module.exports = function (req, res) {
req.url = req.url.toLowerCase();
req.method = req.method.toLowerCase(); if (req.method === 'get') {
// 通过url模块的parse方法获取用户get请求提交的数据
// 第二个参数为true时,urlObj的query属性就是所有的请求参数,类型是json对象
var urlObj = url.parse(req.url, true);
// console.log(urlObj);
req.query = urlObj.query; // query属性就是所有的请求参数,类型是json对象
req.pathname = urlObj.pathname;
} // 封装render函数,将render函数挂在到res对象上;第二个参数是模板数据
// render函数作用:读取html、css、image等静态资源并返回
res.render = function (filename, templateData) {
fs.readFile(filename, function(err, data) {
if(err) {
res.writeHead(404, 'not found', {'Content-Type': 'text/html; charset=utf-8'});
res.end("404, not found.");
return;
} if (templateData) {
var fn = _.template(data.toString("utf-8"));
data = fn(templateData);
} res.setHeader('Content-Type', mime.getType(filename));
res.end(data);
});
};
}

  router.js

// 路由模块
var handler = require("./handler.js"); module.exports = function(req, res) {
if(req.url === '/' || req.url === '/index') {
handler.index(req, res);
}
else if(req.url === '/list') {
handler.list(req, res);
}
else if(req.url.startsWith('/add')) {
handler.add(req, res);
}
else if(req.url.startsWith('/submit') && req.method === 'get') {
handler.getSubmit(req, res);
}
else if(req.url.startsWith('/submit') && req.method === 'post') {
handler.postSubmit(req, res);
}
else if(req.url.startsWith('/detail') && req.method === 'get') {
handler.detail(req, res);
}
else if(req.url.startsWith('/delete') && req.method === 'get') {
handler.deleteBook(req, res);
}
else if(req.url.startsWith('/edit') && req.method === 'post') {
handler.editBook(req, res);
}
else if(req.url.includes('static')){
handler.static(req, res);
}
else {
handler.handler404(req, res);
}
}

  

  handler.js

// 业务模块:负责处理具体路由的业务
var path = require("path");
var fs = require("fs");
var querystring = require("querystring"); var config = require('./config.js'); module.exports = index; // 显示主页
module.exports.list = list; // 显示list页面
module.exports.add = add; // 显示add页面
module.exports.getSubmit = getSubmit; // get请求提交数据:添加book
module.exports.postSubmit = postSubmit; // post请求提交数据:添加book
module.exports.detail = detail; // 显示detail页面
module.exports.deleteBook = deleteBook; // 删除指定id的book
module.exports.editBook = editBook; // 修改book
module.exports.static = static; // 加载静态资源:css、image、js等
module.exports.handler404 = handler404; // 处理404 // 显示主页
function index(req, res) {
res.render(path.join(__dirname, 'pages/index.html'));
} // 显示list页面
function list(req, res) {
// 第一步:读取data.json文件中的数据,转换为list数组
readFile(function(bookList) {
// 第二步:使用模版引擎,将bookList数据和list.html页面结合
res.render(path.join(__dirname, 'pages/list.html'), {msg:'这是list页面', bookList:bookList});
});
} // 显示add页面
function add(req, res) {
res.render(path.join(__dirname, 'pages/add.html'));
} // get请求提交数据:添加book
function getSubmit(req, res) {
// 用户表单提交get请求数据,保存到data/data.json文件中,新数据以追加的形式添加
console.log(req.url); // /summit?name=xxx&price=xxx // 第一步:读取data.json文件中的数据,转换为list数组
readFile(function(list) {
// 第二步:获取get请求的参数,将用户提交的数据添加到json数组
var book = req.query;
book.id = list[list.length - 1].id + 1;
list.push(book);
console.log("添加一条记录后,data.json的内容:" + JSON.stringify(list)); // 第三步:将json数组写入data.json文件,并重定向到list页面
writeFile(list, res);
});
} // post请求提交数据:添加book
function postSubmit(req, res) {
// 用户表单提交post请求数据,保存到data/data.json文件中,新数据以追加的形式添加
getPostBodyData(req, function(book) { // post请求数据封装成book(json对象)
// 读取data.json文件中的数据,转换为list数组
readFile(function(list) {
book.id = list[list.length - 1].id + 1;
list.push(book);
// console.log("添加一条记录后,data.json的内容:" + JSON.stringify(list)); // 将json数组写入data.json文件,并重定向到list页面
writeFile(list, res);
});
});
} // 显示detail页面
function detail(req, res) {
// 第一步:读取data.json文件中的数据,转换为list数组
readFile(function(bookList) {
// 第二步:查询指定id的记录
var book = {};
for (var i = 0; i < bookList.length; i++) {
if (bookList[i].id == req.query.id) {
book = bookList[i];
break;
}
} // 第三步:使用模版引擎,将数据和detail.html页面结合
res.render(path.join(__dirname, 'pages/detail.html'), {book:book});
});
} // 删除指定id的book
function deleteBook(req, res) {
// 第一步:读取data.json文件中的数据,转换为list数组
readFile(function(bookList) {
// 第二步:删除指定id的记录
for (var i = 0; i < bookList.length; i++) {
if (bookList[i].id == req.query.id) {
bookList.splice(i, 1); // 删除起始下标为queryId-1,长度为1的元素
break;
}
} // 第三步:将json数组重新写入data.json文件,并重定向到list页面
writeFile(bookList, res);
});
} // 修改book
function editBook(req, res) {
getPostBodyData(req, function(book) { // post请求数据封装成book(json对象)
console.log("=============book:" + book.id + book.name + book.price);
// 读取data.json文件中的数据,转换为list数组
readFile(function(bookList) {
for (var i = 0; i < bookList.length; i++) {
// console.log("bookList[i].id=" + bookList[i].id);
// console.log("book.id=" + book.id);
console.log(bookList[i].id == book.id);
if(bookList[i].id == book.id) {
bookList[i].name = book.name;
bookList[i].price = book.price;
break;
}
} // 将json数组重新写入data.json文件,并重定向到list页面
writeFile(bookList, res);
});
});
} // 加载静态资源:css、image、js等
function static(req, res) {
res.render(path.join(__dirname, req.url));
} // 处理404
function handler404(req, res) {
res.writeHead(404, 'not found', {'Content-Type': 'text/html; charset=utf-8'});
res.end("404,not found!");
} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 封装读取data.json文件的方法
function readFile(callback) {
fs.readFile(config.dataPath, 'utf-8', function (err, data) {
if(err && err.code !== 'ENOENT') {throw err;}
console.log("data.json原来的内容:" + data); // [{"name":"xxx","price":"xxx"}]]
var bookList = JSON.parse(data || '[]'); // json数组
callback(bookList);
});
} // 封装写入data.json文件的方法
function writeFile(list, res) { // 参数list的类型:json数组
fs.writeFile(config.dataPath, JSON.stringify(list), function(err) {
if(err) throw err;
console.log('写入成功'); // 重定向
res.statusCode = 302;
res.statusMessage = 'Found';
res.setHeader('Location', '/list');
res.end(); // 使用模版引擎,将bookList数据和list.html页面结合
// res.render(path.join(__dirname, 'pages/list.html'), {msg:'这是list页面', bookList:bookList});
});
} // 封装写入data.json文件的方法
function writeFile2(data, callback) { // 参数data的类型:字符串
fs.writeFile(config.dataPath, data, function(err) {
if(err) throw err;
console.log('写入成功'); // 调用callback()来执行当写入数据完毕后的操作
callback();
});
} // 封装获取用户post提交的数据的方法
function getPostBodyData(req, callback) {
var array = []; // 用来保存用户post请求提交的数据
var postBody;
req.on('data', function(chunk) {
// chunk就是浏览器本次data事件提交的一部分数据;chunk是Buffer类型
console.log("data事件...");
array.push(chunk);
}); req.on('end', function() {
console.log("end事件...");
// 把array中多个Buffer对象汇总到一个Buffer对象
var postBody = Buffer.concat(array); // 此处postBody类型:Buffer
// console.log("postBody: " + postBody); // postBody: name=1&price=1
// querystring对象可以把表单数据 name=xxx&price=xxx => {"name":"xxx","price":"xxx"}
postBody = querystring.parse(postBody.toString("utf-8")); // 此处postBody类型:json对象
callback(postBody);
});
}

  config.js

// 配置模块:保存配置信息
var path = require('path'); module.exports = {
port : 8081, // http端口
dataPath : path.join(__dirname, 'data', 'data.json') // data.json文件的路径
}

node.js入门学习(五)--Demo模块化改造的更多相关文章

  1. node.js入门学习(四)--Demo图书的增删改查

    需求:图书的增删改查,图书数据保存在data.json文件中. 1.Demo结构: 2.首先下载安装node.js,配置环境变量:参考博客 3.项目初始化 1)创建项目根目录node-hello,进入 ...

  2. Node.js入门学习笔记(一)

    先来个最常见的"Hello World!". 打开你最喜欢的编辑器(我用的是Sublime Text),创建一个helloWorld.js的文件.我们要做的就是向stdout输出& ...

  3. node.js入门学习(三)--npm

    一.npm介绍 1)npm:node package manager是node.js默认的以js编写的软件包管理系统 官网:www.npmjs.com 文档:docs.npmjs.com 2)提到np ...

  4. node.js入门学习(一)环境安装,REPL,fs模块,path模块,http模块

    一.node.js介绍 1.1.node.js是什么 官网首页总结:Node.js® 是一个基于 Chrome V8 引擎 的 JavaScript 运行时. 1)node.js是一个开发平台,就像j ...

  5. Node.js入门学习笔记(三)

    基于事件驱动的回调 这个问题不好回答,不过这是Node.js原生的工作方式.它是事件驱动的,这也是它为什么这么快的原因.你可以花一点时间阅读一下Felix Geisendörfer的大作 Unders ...

  6. node.js入门学习笔记整理

    (1)node Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node与javaScript的区别在于,javaScript的顶层对象是window,而no ...

  7. node.js入门学习(二)MIME模块,request和response对象,demo之不同url请求不同html页面,页面包含图片、样式css等静态资源

    一.构建http服务程序-根据不同请求做出不同响应 // 加载http模块 var http = require("http"); // 创建一个http服务对象 http.cre ...

  8. node.js入门学习(六)--express

    1.官网:http://expressjs.com/ 中文:http://www.expressjs.com.cn/ 2.HelloWorld 1)mkdir node-express-demo 2) ...

  9. Node.js入门学习笔记(二)

    函数传递 举例来说,你可以这样做: function say(word) {      console.log(word);  }  function execute(someFunction, va ...

随机推荐

  1. java带图形界面的五子棋

    Main: package BlackWhite; import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowL ...

  2. 【神经网络与深度学习】基于Windows+Caffe的Minst和CIFAR—10训练过程说明

    Minst训练 我的路径:G:\Caffe\Caffe For Windows\examples\mnist  对于新手来说,初步完成环境的配置后,一脸茫然.不知如何跑Demo,有么有!那么接下来的教 ...

  3. 跨域设置之corsheaders

    安装 pip install django-cors-headers 注册应用 INSTALLED_APPS = ( ... 'corsheaders', ... ) 中间层设置 MIDDLEWARE ...

  4. 第一个vue程序(极客时间Vue视频笔记)

    第一个vue程序 <body> <div class="app"> {{message}}--{{message+','+message}} <div ...

  5. Linux系统中使用Nignx配置反向代理负载均衡

    目录 使用nginx实现动静分离的负载均衡集群 使用nginx实现负载均衡和动静分离 使用nginx实现动静分离的负载均衡集群 Nginx官网源码包下载链接:http://nginx.org/en/d ...

  6. 多个电脑上免密登陆命令、scp远程拷贝、修改文件的用户和组

    多个电脑上免密登陆命令: 1.ssh-keygen    生成密钥 2.ssh-copy-id   IP 拷贝公钥到指定服务器并授权 3.ssh   Ip 验证登录,已无需输入密码 scp远程拷贝: ...

  7. Luogu P2612 [ZJOI2012]波浪

    题目 我们考虑从\(1\)到\(n\)把每个数放到序列里面去,以消掉绝对值. 在最后的序列中,如果\(i\)的某一边是序列的边界,那么\(i\)会产生\(0\)的贡献.如果\(i\)的某一边是一个比\ ...

  8. Luogu P4602 [CTSC2018]混合果汁

    题目 把果汁按美味度降序排序,以单价为下标插入主席树,记录每个节点的\(sum\)果汁升数和\(val\)果汁总价. 每次询问二分最小美味度,查询美味度大于等于\(mid\)的总体积为\(L\)的最低 ...

  9. fiddler 不能抓包解决

    早上使用金山毒霸扫描了一遍电脑,然后打开fiddler后,出现了一个提示(当时没有注意看),直接点了确定,导致结果是不能抓包了,百度了很多方法,最后直接卸载金山毒霸,然后将防火墙还原为默认设置(风险不 ...

  10. Vue 基础语法入门(转载)

    使用vue.js原文介绍:Vue.js是一个构建数据驱动的web界面库.Vue.js的目标是通过尽可能简单的API实现响应式数据绑定和组合的视图组件.vue.js上手非常简单,先看看几个例子: 例一: ...