Node.js 学习笔记!

本文概述了Node.js学习的第一天内容,包括浏览器的工作原理、Web开发的核心概念、Node.js的特性与安装、以及开发web应用程序与传统方式的区别。重点介绍了HTTP请求处理、渲染引擎、模块化和框架如Express的使用。
摘要由CSDN通过智能技术生成

Node.js学习笔记

Day01

1、浏览器工作原理

1.1 浏览器的组成

人机交互部分(UI)
网络请求部分(Socket)
Javascript引擎部分(解析执行Javascript)
渲染引擎部分(渲染HTML、CSS等);
数据存储部分(cookie、HTML5中的本地存储LocalStorage、SessionStorage);

1.2 渲染引擎

渲染引擎 又叫 排版引擎 或 浏览器内核;

主流的渲染引擎(了解):
在这里插入图片描述

1.3 渲染引擎工作原理

1、解析HTML构建DOM树(Document Object Model,文档对象模型),DOM是W3C组织推荐的处理可扩展置标语言的标准编程接口;
2、构建渲染树,渲染树并不等同于DOM树,因为像head标签或display:none这样的元素就没有必要放到渲染树中了,但是它们在DOM树中;
3、对渲染树进行布局,定位坐标和大小、确定是否换行、确定position、overflow、z-index等等,这个过程叫“layout”或“reflow”;
4、绘制渲染树,调用操作系统底层API进行绘图操作;

1.4 页面reflow 和layout过程

打开Chrome 中Rendering功能
在这里插入图片描述
在这里插入图片描述

1.5 浏览器访问服务器过程

1、在浏览器地址栏输入网站;
2、浏览器通过用户在地址栏中输入的URL构建HTTP请求报文;
3、浏览器发起DNS解析请求,将域名转换为IP地址;
4、浏览器将请求报文发送给服务器;
5、服务器接收请求报文,并解析;
6、服务器处理用户请求,并将处理结果封装成HTTP响应报文;
7、服务器将HTTP响应报文发送给浏览器;
8、浏览器接收服务器响应的HTTP报文,并解析;
9、浏览器解析HTML页面并展示,在解析HTML页面时遇到新的资源需要再次发起请求
10、最终浏览器展示出了页面;

1.6 HTTP请求报文和响应报文格式

在这里插入图片描述

2、web开发本质

2.1 牢记以下三点:

1、请求,客户端发起请求
2、处理,服务器处理请求
3、响应,服务器将处理结果发送给客户端

客户端处理响应:
服务器响应完毕后,客户端继续处理:
浏览器:解析服务器返回的数据;
IOS、Android客户端,解析服务器返回的数据,并且通过IOS或Android的UI技术实现界面的展示功能;

2.2 关于C/S(Client/Server)和B/S(Brower/Server)

C/S:客户端服务器
B/S:浏览器服务器(部署维护方便,用户体验相对一般)

3、node.js

3.1 node.js是什么

1、node.js是一个开发平台,就像java开发平台,.Net开发平台,php开发平台、Apple开发平台一样。
何为开发平台?有对应的编程语言、有语言运行时、有能实现特定功能的API(SDK:Soft Development Kit);
2、该平台使用的编程语言是Javascript语言;
3、node.js平台是基于Chrome V8 Javascript 引擎构建的;
4、基于node.js可以开发控制台程序(命令行程序,CLI程序)、桌面应用程序(GUI)(借助node-webkit、electron等框架实现)、web应用程序(网站);

node.js全栈开发技术栈:MEAN-MongoDB Express Angular Node.js

3.2 node.js的特点

1、事件驱动(当事件被触发时,执行传递过去的回调函数);
2、非阻塞I/O模型(当执行I/O操作时,不会阻塞线程);
3、单线程;
4、拥有世界最大的开源库生态系统——npm;

3.3 node.js 安装和配置

学习目标:
1、了解服务器开发过程
2、会使用node.js开发基本的http服务程序(Web应用程序)

1、安装https://nodejs.org/zh-cn/download/
2、官网术语解释
LTS版本:Long-term Support 版本,长期支持版,即稳定版;
Current版本:Latest Features版本,最新版本,新特性会在该版本中最先加入
3、注意:配置完后,在DOS环境下,输入 node -v,如果有即安装成功,没有需要配置环境变量;
4、通过nvm-windows管理一台计算机上的多个node版本;

3.4 nvm和nvm-windows 介绍

nvm(Node Version Manager) :Node版本管理器**

1、nvm(Linux、Unix、OS X)
https://github.com/creationix/nvm
2、常用命令
nvm install node(安装最新版本的node)
nvm use node(使用指定版本的node)

3、nvm-windows(Windows) 【This is not the same thing as nvm】
https://github.com/coreybutler/nvm-windows
下载安装https://github.com/coreybutler/nvm-windows/releases
4、常用命令
nvm version
nvm install latest
nvm install 版本号
nvm uninstall 版本号
nvm list
nvm use 版本号

3.5 Node.js 开发web应用程序和PHP、java、ASP.net 等传统模式开发web应用程序的区别

传统模式开发:

在这里插入图片描述

Node.js 开发:

在这里插入图片描述

核心区别:

传统方式开发有web容器,在web容器里面写动态页面就可以了。
Node.js开发不需要web容器,因为Node.js本身就是HTTP服务器,每一个请求都是自己来写代码处理。

3.6 REPL介绍

1、REPL全称:Read-Eval-Print-Loop(交互式解释器)
R:读取——读取用户输入,解析输入了Javascript数据结构并存储在内存中;
E:执行——执行输入的数据结构;
P:打印——打印结果;
L:循环——循环操作以上步骤直到用户两次按下ctrl+c 按钮退出;

2、在REPL中编写程序(类似于浏览器开发人员工具中的控制台功能);
直接在控制台输入node命令进入REPL环境;

3、按两次Ctrl+c退出REPL界面 或者 输入.exit退出REPL界面;
按住ctrl 键不要放开,然后按两下c键;

4、Node.js 开发

4.1 Javascript 命名规则

1、不要用中文
2、不要包含空格
3、不要出现node关键字
4、建议以“-”分割单词

4.2 node.js中单线程——非阻塞IO解释

V8里面并没有包含DOM对象、window对象,setTimeout对象等等;Javascript 这个JS引擎V8里面只有两个东西:一个就是堆,一个就是调用栈(栈的特点是先进后出);
在线动画演示:http://latentflip.com/loupe
参考视频https://www.youtube.com/watch?v=8aGhZQkoFbQ
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.3 fs 模块

4.3.1 fs.writeFile(file, data[, options], callback) 写入文件操作

fs模块必须通过require加载
原因:fs模块不是全局模块,全局模块( console 和 process 是全局模块)可以直接使用,而非全局模块需要先通过require("")加载该模块;

第一个参数是文件路径:
file <string> | <Buffer> | <URL> | <integer> filename or file descriptor

第二个参数是要写入的数据:
data <string> | <Buffer> | <TypedArray> | <DataView> | <Object>

第三个参数可选:
options <Object> | <string>
        encoding <string> | <null> Default: 'utf8'
        mode <integer> Default: 0o666
        flag <string> See support of file system flags. Default: 'w'.

第四个参数是回调函数:
callback <Function>
        err <Error>
// 实现文件写入操作
// 1、加载文件操作模块,fs模块
const fs = require("fs");

// 2、实现文件写入操作
var msg = "hello world";
// 调用fs.writeFile(file, data[, options], callback)
fs.writeFile("./files/hello.txt",msg,function (err){
    // 如果error === null,表示写入文件成功,没有错误
    // 如果error !==null,表示写入文件失败
     if(err) {
         console.log("写入文件失败"+err);
     } else {
   console.log("ok");
  }
});
4.3.2 fs.readFile(path, [, options], callback) 写入文件操作
第一个参数:
path <string> | <Buffer> | <URL> | <integer> filename or file descriptor

第二个参数:
options <Object> | <string>
        encoding <string> | <null> Default: null
        flag <string> See support of file system flags. Default: 'r'.
        
第三个参数:
callback <Function>
         err <Error>
         data <string> | <Buffer>
// ---------------实现文件读文件--------------
const fs = require("fs");

// 在读取文件的时候,如果传递了参数编码,那么回调函数中的data默认就会转换为字符串
fs.readFile("./files/hello.txt", 'utf-8', function(err,data) {
  if(err) {
    throw err;
  } else {
    // data参数的数据类型是一个Buffer对象,里面保存的就是一个一个的字节(理解为字节数组
    // 把buffer对象转换为字符串,调用toString()方法
    // console.log(data.toString());
    console.log(data);
  }
})
4.3.3 __dirname 和 __filename 获取正在执行的js文件的路径

1、小贴士:错误都是大写E开头;

2、解决在文件读取中,./相对路径的问题
__dirname :表示当前正在执行的js文件所在的目录
__filename:表示当前正在执行的js文件的完整目录
在这里插入图片描述
在这里插入图片描述

3、__dirname 和 __filename 并不是全局的

4.4 path 模块 (进行路径拼接)

4.4.1 path.join([…paths])

在这里插入图片描述

4.5 http 模块

4.5.1 创建一个简单的http服务器程序:

(1)加载http模块

const http = require('http');

(2)创建一个http服务对象

var server = http.createServer();

(3)监听用户的请求事件(request事件)
request对象
包含了用户请求报文中的所有内容,通过request对象可以获取所有用户提交过来的数据
response对象
用来向用户响应一些数据,当服务器要向客户端响应数据的时候必须使用response对象
有了request对象和response对象,就既可以获取用户提交的数据,也可以向用户响应数据了

注意:
对于每一个请求,服务器必须结束响应,否则客户端(浏览器)会一直等待服务器响应结束;

server.on('request', function (request, response){
    // 对于每一个请求,服务器必须结束响应,否则客户端(浏览器)会一直等待服务器响应结束;
    response.end('ok');
});

(4)启动服务

server.listen(3000, function(){
    console.log("http://localhost:3000");
})
(1)通过服务器端设置响应报文头来解决乱码问题
response.setHeader('Content-Type','text/plain;charset=utf-8');
(2)通过设置http响应报文头来解决浏览器显示html的问题

在这里插入图片描述

4.5.2 构建http服务程序-根据不同请求做出不同响应

在这里插入图片描述

4.5.3 根据用户不同请求-读取不同HTML文件响应
// 1、加载http模块
const http = require("http");
// 加载fs模块
const fs = require("fs");
// 加载path模块
const path = require("path");


// 2、创建服务并监听开启服务
http.createServer(function(req,res) {

    if(req.url === '/'|| req.url ==='/index') {
        // 读取index.html
        fs.readFile(path.join(__dirname,'htmls','index.html'), function (err,data) {
            res.end(data);
        });
    } else if (req.url === '/login') {
        // 读取login.html
        fs.readFile(path.join(__dirname,'htmls','login.html'), function (err,data) {
            res.end(data);
        });
    } else {
       // 读取404.html
       fs.readFile(path.join(__dirname,'htmls','404.html'), function (err,data) {
        res.end(data);
    });
    }

}).listen(3000, function(){
    console.log("server listening http://localhost:3000");
})
4.5.4 try-catch与异步操作

try-catch只能捕获同步操作的错误,无法捕获异步操作的异常;
对于异步操作,要通过判断错误号(err.code)来判断;

4.5.5 根据用户不同请求响应不同的html页面(带图片)

HTTP Mime-Type:https://tool.oschina.net/commons
在这里插入图片描述
在这里插入图片描述

4.5.6 根据用户不同请求响应不同的html页面(带css)

在这里插入图片描述
在这里插入图片描述

Day02

1、http模块

1.1 模拟Apache服务器

const http = require('http');
const path = require('path');
const fs = require('fs');
// 加载mime模块,判断不同资源对应的Content-Type类型
const mime = require("mime");


http.createServer(function(req,res) {
    
    var publicDir = path.join(__dirname,'public');
    var filename = path.join(publicDir, req.url);
    fs.readFile(filename, function (err, data){
        if(err) {
            throw err;
        } else {
            res.setHeader("Content-Type", mime.getType(filename));
            res.end(data);
        }
    })
}).listen(3000, function(){
    console.log("Server http://localhost:3000");
})

1.1.1 mime 模块 (第三方模块,判断不同的资源对应的Content-Type类型)

第三方模块,根据后缀名判断不同资源对应的Content-Type类型;
https://www.npmjs.com/package/mime

1.2 对于服务器来说请求url就是一个标识符 在这里插入图片描述

1.3 request对象常用属性

request:服务器解析用户提交的http请求报文,将结果解析到request对象中,凡是要获取和用户请求相关的数据都可以通过request对象获取;
response:在服务器端用来向用户做出响应的对象,凡是需要向用户(客户端)响应的操作,都需要通过response对象来进行;

request 对象常用成员
(1)request.headers:返回的是一个对象,这个对象包含所有的请求报文头;
(2)request.rawHeaders:返回的是一个数组,数组中保存的都是请求报文头的字符串;
(3)request.httpVersion:获取请求客户端所使用的http版本;
(4)request.method:获取客户端请求所使用的方法;
(5)request.url:获取这次请求的路径(获取请求报文中的请求路径,不包括主机名、端口、协议);

1.4 response对象常用成员

response 对象常用成员
(1)response.write()
(2)response.end():告诉服务器该响应的报文头、报文体都已被发送,即服务器将其视为已完成;要响应数据的话,数据必须是string 或Buffer 类型,每次响应都必须调用response.end()方法;
(3)response.setHeader():设置响应报文头,这个要放在前面设置;
(4)response.statusCode:设置HTTP响应状态码;
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
(5)response.statusMessage:设置HTTP响应状态码对应的消息;
(6)response.writeHead(statusCode[, statusMessage][, headers]):直接向客户端响应(写入)http响应报文头(系统默认会调用这个方法);

2、npm 介绍(Node package Manager —Node包管理器)

官网:https://www.npmjs.com/
官方文档:https://docs.npmjs.com/

我们提到npm,一般指以下三个:
(1)npm 网站
(2)npm代码仓库
(3)npm命令( npm 客户端 )

在这里插入图片描述

2.1 npm 和 node.js

(1)NPM官方解释:

npm是一个Javascript包管理器,并且是世界上最大的软件登记处;
发现可重用代码,并集成代码包到项目中的全新的、强大方式;
npm让Javascript开发者共享和重用代码变的更容易,同时也让我们更容易地更新正在被共享的代码;

(2)npm与node.js:

npm 是Node.js默认的软件包管理系统。安装完毕node后,会默认安装好npm;
npm本身也是基于Node.js开发的包(软件,一个客户端的命令行工具);

如何安装npm:
npm会随着Node.js自动安装,安装完毕node.js后会自动安装npm;
查看当前npm版本:npm -v;
更新npm:npm install npm@latest -g;

(3)NPM使用(本地安装):

1、在https://www.npmjs.com网站找到需要的包;
2、在项目的根目录下,执行:npm install 包名称 安装;
3、在node.js代码中通过require('包名');加载该模块;
4、注意:通过npm install 包名安装的包,会自动下载到当前目录下的node_modules目录下,如果该目录不存在,则创建,如果已存在则直接下载进行。
5、在代码中通过require('包名');加载该模块;

(4)NPM全局安装介绍:

1、什么是npm全局安装?
npm install 包名 -gnpm全局安装指的是**把包安装成一个命令行工具;**

// 通过npm全局安装mime
npm install mime -g;

// 安装完毕之后可以在命令行中直接使用
mime a.txt 命令来查看对应的结果

2、npm全局安装实际做了2件事:
(1)下载包到一个指定的目录:C:\Users\zrf\AppData\Roaming\npm\node_modules;
(2)创建一段命令行执行的代码

(5)NPM安装建议:

全局安装只是为了可以当做命令行使用而已;

(6)npm 常用命令

1、install ,安装包,npm install 包名
2、uninstall, 卸载包,npm install 包名;
3、version, 查看当前npm版本。npm versionnpm -v;
4、init,创建一个package.json文件。npm init;
5、注意:当使用npm init -y的时候,如果当前文件夹(目录)的名字比较怪(有大写,有中文等等)就会影响npm init -y的一步生成操作,此时需要npm init根据向导来生成;

3、Modules和 packages区别

1、模块可以是任何一个文件或目录(目录下可以有很多个文件),只有能被node.js通过require()加载的叫做模块;
2、包是一个文件或目录(目录下可以有很很多个文件),必须有一个package.json文件来描述,就可以是一个包;

npm中的所有代码都是包,只有通过require()能加载的才能叫做模块;
在npm仓库中的模块就是包,如果不是npm仓库的,是模块不一定是包,必须有一个package.json来描述的,才可以叫做包;

4、package.json 文件介绍

4.1 package.json 文件的作用:

1、package.json文件是一个包说明文件(项目描述文件),用来管理组织一个包(一个项目);
2、package.json文件是一个json格式的文件;
3、位于当前项目的根目录下;

4.2 package.json文件中常见的项有哪些?

name:包的名字;
version:包的版本;
description:包描述;
author:包的作者;
main:包的入口js文件,从main字段这里指定了哪个js文件开始执行;
dependencies:当前包依赖的其他包;

4.3 如何创建一个package.json文件

1、通过npm init命令或者npm init -y或者npm init -yes命令;
2、手动创建一个

注意:
1、通过npm init -y或者npm init -yes创建package.json文件时,执行命令所在的目录名称中不能包含大写字母;
2、package.json文件中,项目名称本身不能包含大写字母;
3、npm更新新版本后,项目所在的文件夹如果包含中文等特殊字符,创建的时候不会提示一步一步的输入,直接报错;

5、package-lock.json 文件介绍

yarn命令行工具

npm5版本开始引进的新文件,借鉴yarn
主要是一些包的依赖和包的详细信息,使得我们下载的时候变的很快;

Day03

1、路由

设计路由:提前想好当用户用什么方法请求什么路径的时候做出什么样的响应;
路由:请求方法加请求路径;

2、封装render函数

// 封装一个render函数
function render(filename, res) {
    fs.readFile(filename,function (err,data){
        if(err) {
            throw err;
        } 
        res.setHeader('Content-Type', mime.getType(filename));
        res.end(data);
    })
}

3、将render函数挂在到res对象上

将render函数挂载到res对象上,可以通过res.render()来访问;
为res对象添加一个render()函数,方便后续使用

// 将render函数挂载到res对象上,可以通过res.render()来访问
    // 为res对象添加一个render()函数,方便后续使用
    res.render = function (filename) {
        fs.readFile(filename,function (err,data){
            if(err) {
                throw err;
            } 
            res.setHeader('Content-Type', mime.getType(filename));
            res.end(data);
        })
    }

4、url模块

4.1 通过使用url模块的parse方法获取用户get提交的数据

url.parse(urlString[, parseQueryString[, slashesDenoteHost]])(官网显示已弃用)

第一个参数 urlString:要解析的url
第二个参数 parseQueryString:如果为true,则query属性将始终设置为querystring模块的parse()方法返回的对象。如果为false,则返回的URL对象的query属性将是一个未解析、未解码的字符串。
第三个参数 slashesDenoteHost:如果为真,字面值//之后的第一个标记,下一个/之前的标记将被解释为主机。例如,给定//foo/bar,结果将是{host: ‘foo’, pathname: ‘/bar’}而不是{pathname: ‘//foo/bar’}

核心代码:

var urlObj = url.parse(req.url, true);

5、服务器端通过设置http响应报文头实现浏览器重定向操作

思想:服务器想让浏览器做什么,就是发响应报文头告诉浏览器做什么
重定向原理(设置响应报文头)

核心代码:

             // 3.跳转到新闻列表页
            // 设置响应报文头告诉浏览器,执行一次页面跳转操作
            // 重定向原理(设置响应报文头)
            // 思想:服务器想让浏览器做什么,就是发响应报文头告诉浏览器做什么
            res.statusCode = 302;  // 以3开头的状态码都是跳转
            res.statusMessage = "Found";
            res.setHeader('Location', '/');

忘记的小知识:把数组转换为字符串JSON.stringify(list);

6、get方式提交防止原先数据被覆盖掉

思路:先读取文件,把文件数据转换为数组,文件不存在就创建数组,再push数据;
因为第一次访问网站,data.json文件本身就不存在,所有肯定是有错误的,但是这种错误,我们并不认为是网站出错了,所以不需要抛出异常

// 1.1 读取data.json文件中的数据,并将读取到的数据转换为一个数组
        fs.readFile(path.join(__dirname,'data','data.json'),'utf8', function (err){
            // 因为第一次访问网站,data.json文件本身就不存在,所有肯定是有错误的
            // 但是这种错误,我们并不认为是网站出错了,所以不需要抛出异常
            if(err && err!=='ENOENT') {
                throw err;
            }
            // 如果读取到数据了,那么久把读取到的数据data转换为list数组
            // 如果没有读取到数据,那么就把'[]'转换为数组
            var list = JSON.parse(data || '[]');
            list.push(urlObj.query);
            
            fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(list), function (err) {
                if (err) {
                    throw err;
                }
                res.statusMessage = "Found";
                res.setHeader('Location', '/');
                res.end();
            });
        });

7、querystring模块

7.1 querystring模块的parse方式解析post提交的数据

// 把字符串转换为json对象
                postBody = querystring.parse(postBody);

7.2 获取post提交的数据并且保存在data.json文件中(核心代码)

**核心思路:**因为post提交数据的时候,数据量可能比较大,会分多次进行提交,所以会分多次提交,此时要想在服务器中获取用户提交的所有数据,就必须监听request事件的data事件(因为每次浏览器提交一部分数据都服务器就会触发一次),那么什么时候才表示浏览器把所有数据都提交到服务器了?就是当request对象的end事件被触发的时候。

 // 表示post方式提交数据
        // 1、 读取data.json文件中的数据,并将读取到的数据转换为一个数组
        fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf8', function (err, data) {
            if (err && err !== 'ENOENT') {
                throw err;
            }
            var list = JSON.parse(data || '[]');
            // 2、获取用户post提交的数据
            // 因为post提交数据的时候,数据量可能比较大,会分多次进行提交,所以会分多次提交
            // 此时要想在服务器中获取用户提交的所有数据,就必须监听request事件的data事件(因为每次浏览器提交一部分
            // 数据都服务器就会触发一次),那么什么时候才表示浏览器把所有数据都提交到服务器了?就是当request对象的end
            // 事件被触发的时候。

            // 监听request的对象的data事件和end事件代码如下:
            var array = []; //用来保存每次用户提交过来的数据
            req.on('data', function (chunk) {
                // 此处的chunk参数,就是浏览器本次提交过来的一部分数据
                // chunk的数据类型是buffer,(chunk就是一个buffer对象)
                array.push(chunk);
            });

            // 监听request对象的end事件
            // 当end事件被触发的时候,数据都已经提交完毕了
            req.on('end', function () {
                // 在这个事件中只要把array中的所有数据汇总起来就好了
                // 把array中的每个buffer对象集合起来转换为一个buffer对象
                var postBody = Buffer.concat(array);
                // 把buffer对象转换为字符串
                postBody = postBody.toString();
                // 把字符串转换为json对象
                postBody = querystring.parse(postBody);
                // 将用户提交的数据push进去
                list.push(postBody);
                // 把list数组中的数据写入到data.json文件中
                fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(list), function (err) {
                    if (err) {
                        throw err;
                    }
                    res.statusCode = 302;
                    res.statusMessage = "Found";
                    res.setHeader('Location', '/');
                    res.end();
                });
            });
        });

8、underscore模块使用(JS工具函数库)

https://www.npmjs.com/package/underscore

template函数:
https://underscorejs.org/#template

var _ = require("underscore");

// 声明了一段模板代码的html文档
var html = '<h1><%= name%></h1>';
// 返回值依然是一个函数

var fn = _.template(html);

// 调用template()返回的这个函数fn
// fn接收一个数据对象,并用该数据对象,将html中的模板内容替换,生成最终的html代码
var html = fn({name:"daa"});
console.log(html);  //<h1>daa</h1>

在这里插入图片描述

9、在添加数据的时候添加id,通过id来显示数据详情

Day04

1、封装读取data.json文件的方法

核心:
如果要封装一段代码,里面包含异步操作,要想拿到结果,封装的这个方法也必须传一个回调函数进来;

// 封装读取data.json文件的方法
function readNewsData(callback){
    fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf8', function (err, data) {
        if (err && err !== 'ENOENT') {
            throw err;
        }
        var list_news = JSON.parse(data || '[]');
        callback(list_news);
    });
}

2、封装写入data.json文件的方法

// 封装写入data.json文件的方法
function writeNewsData(data, callback) {
    fs.writeFile(path.join(__dirname, 'data', 'data.json'), data, function (err) {
        if (err) {
            throw err;
        }

        // 调用callback回调函数来执行写入数据完毕之后的操作
        callback();
    });
}

3、node.js中模块的分类

第一类:核心模块(内置模块或原生模块);
path、http、fs、url …
所有内置模块在安装node.js的时候就已经编译成二进制文件,可以直接加载运行(速度较快);
部分内置模块,在node.exe这个进程启动的时候就已经默认加载了,可以直接使用;

第二类:文件模块,一个js模块就是一个模块;
1、.js
2、.json
3、.node(c/c++编写的模块)

第三类:自定义模块(第三方模块);
mime、mongo…

4、require函数加载模块

4.1 require函数加载模块过程

情况一:require()的参数不是路径,直接就是一个模块名称;
require('mime');

1、先在核心模块中查找,是否有和给定的名字一样的模块,如果有,则直接加载该核心模块;
2、如果核心模块中没有该模块,那么就会认为这个模块是一个第三方模块(自定义模块),先会去当前js文件所在的目录下去找是否有一个node_modules文件夹,如果有直接加载,如果没有,一层一层向上找,一直到根目录,没有则加载失败;

情况二:require()的参数是一个路径
require('./index.js'); //有后缀
require('./index'); //没有后缀

查找路径:
index.js
index.json
index.node
index文件夹—>package.json---->main(入口文件app.js)——>index.js---->index.json--->index.node-->加载失败

4.2 require函数加载模块时的注意点

1、所有模块第一次加载完毕后都会有缓存,二次加载直接读取缓存,避免了二次开销
2、每次加载模块的时候都优先从缓存中加载,缓存中没有的情况下才会按照node.js加载模块的规则去查找;
3、核心模块在Node.js源码编译的时候,都已经编译为二进制执行文件,所以加载速度较快(核心模块的优先级仅次于缓存加载);
4、核心模块都保存在lib目录下;
5、视图加载一个和核心模块同名的自定义模块(第三方模块)是不会成功的;要么使用路径的方式加载;
6、核心模块只能通过模块名称来加载;
7、require()加载模块使用./相对路径时,相对路径时相对当前模块,不受执行node命令的路径影响;
8、建议加载文件模块的时候始终添加文件后缀名,不要省略;

4.3 require函数加载模块原理(被加载的模块会先执行一次)

在任何一个js文件中都可以使用require这个函数,它是属于Module的;

5、 CommonJS 规范

1、【CommonJS 规范】
2、【模块的定义】
3、总结:CommonJS是为了Javascript语言制定的一种 模块规范、编程API规范;
4、node.js遵循了 CommonJS规范;

6、 module.exports介绍

两个模块之间通信使用module.exports;
默认module.exports = {};

6.1 module.exports 和 exports的区别

默认情况下,module.exports和exports指向的是同一个对象;
最终,require函数返回的是module.exports;

module.exports.name = "zhsnags";
exports.age = 18;
exports.show = function () {
    console.log(this.name + this.age);
}

module.exports = "hello world!"

var a = require('./01-module.exports.js');
console.log(a);   // hello world!

在这里插入图片描述

module.exports.name = "zhsnags";
exports.age = 18;
exports.show = function () {
    console.log(this.name + this.age);
}

exports = "hello world!"
var a = require('./01-module.exports.js');
console.log(a);  //{ name: 'zhsnags', age: 18, show: [Function (anonymous)] }

7、 模块化思路

便于维护代码;便于多人开发;
按照功能模块,把代码提取到不同的js文件里面;

模块一(服务模块):启动项目
模块二(扩展模块):为response扩展方法,为res和req函数增加一些更方便好用的API
模块三(路由模块):路由判断
模块四(业务模块):处理具体路由的业务代码
模块五(数据操作模块):负责进行数据库操作
模块六(配置模块):放置项目中各种配置信息

Day02

1、Buffer类型介绍

Buffer类型产生的原因?主要用来解决什么问题?
1、Buffer使用来临时存储一些数据(二进制数据);
2、当我们要把一大块数据从一个地方传输到另外一个地方的时候可以通过Buffer对象进行传输;
3、通过Buffer每次可以传输小部分数据,直到所有数据都传输完毕;

看一下什么是Buffer?什么是Stream?

一、类型介绍
1、JavaScript语言没有读取或操作二进制数据流的机制;
2、Node.js中引入了Buffer类型使我们可以操作TCP流或文件流;
3、Buffer类型的对象类似于整数数组,但Buffer的大小是固定的、且在V8堆外分配物理内存。Buffer的大小在被创建时确定,且无法调整。(buf.length是固定的,不允许修改);
4、Buffer是全局的,所以使用的时候无需require()的方式来加载;

2、express框架

2.1 express介绍

(1)基于node.js开发的“web开发框架”,就是node.js的一个模块;
(2)express的作用:它提供一系列强大的特性,帮助你创建各种web和移动设备应用;
(3)express同时也是node.js的一个模块;

2.2 为什么要学习express框架

为了让我们基于node.js开发web应用程序更高效。

2.3 express官方网站

http://expressjs.com
http://www.expressjs.com.cn

2.4 express 特点

1、实现了路由功能;
2、中间件( 函数)功能;
3、对req和res对象的扩展;
4、可以集成其他模板引擎(第三方);

2.5 express 基本使用

安装express
npm搜索,安装。按照文档一步一步进行;
1、创建package.json文件
2、安装express模块,npm install express

最简单的express的使用:

// 入口文件

// 1.加载express模块
var express = require('express');

// 2.创建一个app对象(类似于创建一个server对象)
var app = express();

// 通过中间件监听指定的路由的请求
app.get('/index', function(req, res){
    res.end("hello world");
})

// 3.启动服务
app.listen(9000,function(){
    console.log("Listening on http://localhost:9000");
})

2.6 res.send()和res.end()区别

1、参数类型区别:
res.end()只能支持string或者buffer;res.send()支持更多类型的参数
2、res.send()会自动发送更多的响应报文头,所以没有乱码;

2.7 app.get()和app.use()注册路由的区别

// 含义:1、请求方法必须是get
// 2、请求路径pathname,必须是=== /index
app.get('/index', function(req, res){
    res.end("hello world");
})

// 在进行路由匹配的时候,不限定方法,什么请求方法都可以
// 2、请求路径中的第一部分只要与/index相等即可,并不要求请求路径pathname完全匹配
app.use('/submit', function(req,res){
    res.send("hello submit");
})

2.8 app.all()注册路由

1、不限定请求方法;
2、请求路径必须完全匹配;

// 在进行路由请求时,1、不限定方法;2、请求路径必须完全匹配
app.all('/item', function(req, res){
    res.send("hello item");
})

2.9 通过正则表达式注册路由

app.get(/^\/index(\/.+)*$/, function(req, res){
    res.end("hello world");
})

2.10 通过req.params获取路由中的参数

// 通过req.params获取路由中的参数
app.get('/news/:year/:month/:day',function(req, res){
    res.send(req.params);
})

2.11 通过express模拟Apache实现静态资源托管服务

核心:

// var fn = express.static(path.join(__dirname,'public'));
// console.log(fn.toString());
// app.use('/', fn);

// 处理静态资源 核心代码就这一句话
// /xxx叫做虚拟路径
app.use('/xxx', express.static(path.join(__dirname,'public')))

2.12 res对象的常见方法

1、res.json() 等价于 res.send(json);
2、res.redirect()
3、res.sendFile()
4、res.status(code).end()

2.13 res.sendFile()和res.render

sendFile()方法虽然可以读取对应的文件返回,但是我们不使用sendFile()方法
原因是:将来我们要对index.html中的模板代码进行执行并替换
默认render方法是不能使用的,需要为express配置一个模板引擎,然后才可以使用

2.14 ejs模板引擎使用

https://www.npmjs.com/package/ejs

const ejs = require('ejs');

var html = '<h1><%= username%></h1>';
var result = ejs.render(html,{username:"sasa"});

console.log(result);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值