NODE.JS
什么是node.js?
-
Node.js® is a JavaScript runtime(运行时、运行环境) built on Chrome's V8 JavaScript engine.
Node.js 是一个构建于 Chrome V8 引擎的 JavaScript 运行环境。
Node.js 为 JavaScript 代码的正常运行,提供的必要的环境。
不是库、框架、不是语言。
是一个JS运行时环境。简单说就是可以解析和执行JS代码。
像浏览器一样提供可以解析和执行的环境,但不是浏览器。以前只有浏览器可以解析和执行js代码,有了node.js,现在可以脱离浏览器去解析和执行。
(技术性的网站一般都是io或者org)
-
浏览器中的javaScript:
-
ECMAScript(语法)
基本的语法
if语句
var
function
objeck
array
DOM
BOM
-
-
node.js中的javaScrip:
没有DOM和BOM。(服务端不负责处理处理DOM和BOM)
有ECMAScript
-
在node这个JavaScript执行环境中为JavaScript提供了一些操作服务器级别的API。如:
文件的读写
网络服务的构建
数据网络通信
http服务器。。。
-
node.js 的特点
单线程,非阻塞I/O,事件驱动。
相比多线程语言更节省内存,非阻塞I/O使得程序不停在运行,事件驱动可以处理I/O后的回调。
单线程则系统不会再用于建立销毁线程增加开销,不过线程出问题,全部业务都出问题。
在非阻塞模式下,一个线程永远在计算,线程CPU核心利用率永远100%。
npm是最大的开源库生态系统。(node.js开发的)绝大多数的JavaScript相关的包都存放在npm上面,这样做的目的是为了使开发人员更方便的使用和下载。
Node.js能做什么
web服务器后台,网站后台
-
命令行工具
npm
git(c语言开发的)
hexo(node开发的)
对于前端开发工程师来说,接触node最多的是命令行工具,自己写的很少,主要是使用第三方工具
可以学到什么
-
B/S编程模型
Browser-server
back-end
任何服务端奇数这种BS编程模型都是一样的,和语言无关
Node只是作为我们学习BS编程模型的一个工具
-
模块化编程
RequireJS
SeaJS
在Node中可以像
@import('w文件路径')
一样来引用加在JavaScript脚本文件
Node常用API
-
异步编程
回调函数
Promise
async
agenerator
ES6新语法
global模块
global模块,是node的全局模块,在使用时不需要引入,可以直接使用。
* window 顶层对象 全局变量
* global 全局模块 里面的变量 , 都是全局变量
* 注意 : node里面使用 global里面的变量,不需要引入 , 说明其他的是需要引入的
*/
//1\. console.log() 打印
//2\. setTimeout 和setInterval ,延时器和定时器
setTimeout(() => {
console.log('123');
}, 1000);
//3\. __dirname 当前文件夹的绝对路径
//从当前所在磁盘盘符一直到当前文件夹的路径
console.log(__dirname);
//4\. require 引入模块
// 在node里是通过require 来引入模块的
// 除了global其他模块都是需要引入的
const fs = require('fs')
</pre>
Node中的JavaScript
-
EcmaScript
- 没有DOM、BOM
核心模块
核心模块
Node为JavaScript提供了很多服务器级别的API,这些API绝大多数都被包装到了一个具体的核心模块中了。例如操作文件的fs核心模块,http服务构建的http模块。。如果需要使用核心模块,就必须先引入const fs = require('fs')
fs 文件系统核心模块
fs是file-s 的简写,他是node.js提供的用来操作文件的模块。在fs这个核心模块中,就提供了所有文件操作相关的API。使用文件系统模块之前,先i引入fs模块:conts fs = require('fs')
(浏览器中的JavaScript没有文件操作的能力,node.js中有操作文件的能力)浏览器不认识node代码
-
向指定文件读取内容:fs.readFile()
-
fs.readFile(path[, options], callback)
参数1:必选,指定文件的路径
参数2:可选,表示以什么编码格式读取
-
参数3:必选,回调函数。
第一个参数err(错误内容),读取成功会返回null。
第二个data(读到的数据)
-
-
向指定文件书写内容:fs.writeFile()
-
fs.writeFile(file, data[, options], callback)
参数1:必选,指定文件的路径
参数2:必选,要书写的文件内容
参数3:可选,以什么格式写入,默认为'utf8'
参数4:必选,回调函数。参数err(错误内容),读取成功会返回null
【注】1、以覆盖的形式写入文件
2、写入的文件不存在,会新创建一个文件
-
-
读取指定目录下所有文件的名称:fs.readdir()
-
fs.readdir(path[, options], callback)
参数1:必选,指定要读取哪个目录下所有的文件名称
参数2:可选,以什么格式读取目录
参数3:回调函数
-
path 路径核心模块
path 模块是 Node.js 官方提供的、用来处理路径的模块。使用之前需要先引入const path = require('path')
-
路径拼接path.join()
path.join([...paths])
paths <string> 多个路径片段的序列,返回值string
默认按照拼接顺序拼接
-
获取路径中的文件名path.basename()
可以从一个文件路径中,获取到文件的名称部分
path.basename(path[,ext])
path <string> 必选参数,表示一个路径的字符串
ext <string> 可选参数,表示可选的文件扩展名
返回: <string> 表示路径中的最后一部分,如果不存在路径,全部都是文件名。路径存在,取最后一个斜杠后面的内容
http核心模块
http 模块是 Node.js 官方提供的、用来创建web 服务器和客户端的模块。使用之前需要先引入const http= require('http')
创建 web 服务器的基本步骤
导入http核心模块
使用
http.creatServer()
方法创建一个web服务器,返回一个Server实例给Server实例绑定request 事件,监听客户端的请求。当客户端发送请求过来,会触发服务器的request请求事件,然后执行回调函数
绑定端口号,启动服务器(不要设置6666)
示例代码
// 1\. 加载 http 模块
const http = require('http');
// 2\. 创建server 对象
const server = http.createServer();
// 3\. 监听端口,开启服务器
server.listen(3000, () => console.log('my server running'));
// 4\. 注册server的request事件,准备处理浏览器的请求
server.on('request', (req, res) => {
// req request 请求,通过req对象可以获取到所有和请求相关的信息
// res response 响应,通过res对象可以做出响应以及设置一些和响应相关的内容
// // 设置响应头
// res.setHeader('Content-Type', 'text/html; charset=utf-8');
// res.setHeader('Author', 'zhangsan'); // 自己设置响应头,不要用中文
// // 设置响应状态码
// res.statusCode = 200;
// 综合性的设置响应状态码和响应头的方法
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8',
'Author': 'zhangsan'
});
// write方法,也可以设置响应体,但是没有做出响应的意思,只是单纯的设置响应体
res.write('1234');
res.write('5678');
// res.end(响应体); // 做出响应
res.end('hello,你的请求我收到了');
// 做出响应之后,不能再有其他代码。
});</pre>
【注意】如果代码修改,要重启服务器才能
Request请求事件处理函数,需要接收两个参数,分别是Request请求对象和Response响应对象
Request 请求对象
可以用来获取客户端的一些请求信息,例如请求路径、方式、头、体,所有和请求相关的信息,都可以获取到。
获取请求地址
req.url
获取请求方式
req.method
Response 响应对象
可以用来给客户端响应消息。有一个方法res.write()
可以用来给客户端发送响应的数据。write()
方法可以使用多次,但最后一定要用end()
结束响应,否则客户端会一直等待。可以在响应结束的时候,
-
设置响应头,解决中文乱码
res.setHeader('Content-Type', 'text/html; charset=utf-8');
-
设置状态码
res.statusCode = 200;
-
综合设置响应头和状态码的方法
res.writeHead(200,{'Content-Type', 'text/html; charset=utf-8','Author':'ls'})
-
响应体
res.write()
- 结束响应
res.end()
- 结束响应
【注】
所有的请求路径 url 都是以 / 开头的
响应内容只能是字符串或者二进制数据
当请求不同的路径的时候,响应不同的结果。
例如请求:
/ index ,响应index
/login,响应login
/haha,响应哈哈
server.on('request', (req, res) => {
// 获取请求路径。再根据路径响应
// 所有的请求路径 url 都是以 / 开头的
var url = req.url
if (url === '/index' || url === '/') {
res.end('index page')
} else if (url === '/login') {
res.end('login page')
} else if (url === '/haha') {
res.end('haha page')
} else {
res.end('404 Not Found')
}
})</pre>
端口号
计算机中的端口号,就好像是现实生活中的门牌号一样。通过门牌号,外卖小哥可以在整栋大楼众多的房间中,准确把外卖 送到你的手中。
同样的道理,在一台服务器中,可以运行成百上千个web 服务。此时,通过端口号,客户端发送过来的网络请求,可以被准 确地交给端口号对应的web 服务进行处理。
npm初步使用
npm(node package manager)node包管理器。
包是什么?包就是模块。
npm这个工具,在安装node的时候,就已经安装到你的计算机中了。
命令行中执行:
npm -v
,如果看到版本号,说明安装成功了。
作用
npm的作用是:管理node模块的工具。
下载并安装第三方的模块
卸载第三方模块
发布模块
删除已发布的模块
....
npm 就是一个管理(下载安装、卸载...)第三方模块的工具
第三方模块:
非内置模块,安装完node,还不能使用的模块,需要从网上下载安装,才能使用的模块
第三方模块是个人、公司、组织编写的模块,发布到网上,供我们使用
初始化
使用npm工具之前,必须先初始化。
npm init -y
或
npm init
然后一路回车
初始化之后,会在项目目录中生成 package.json 的文件。
什么第三方模块
非node自带的模块。
是别人写的模块,然后发布到npm网站,我们可以使用npm工具来下载安装别人写的模块。
第三方模块,都是在node核心模块的基础之上,封装了一下,实现了很多非常方便快速简洁的方法。
目前,npm网站收录了超过 150万个第三方模块。
安装卸载项目模块
下载安装第三方模块
npm install 模块名
npm i 模块名
卸载模块
npm uninstall 模块名
npm un 模块名</pre>
安装指定版本:
npm i 模块名@版本号
npm i jquery@3.5.0</pre>
演示代码
这里演示一个处理时间日期的模块 -- moment
下载安装moment模块
npm init -y
npm i moment</pre>
演示使用moment模块处理时间
// 加载模块
const moment = require('moment');
console.log(moment().format('YYYY-MM-DD hh:mm:ss'));
// 官网:http://momentjs.cn</pre>
全局模块
全局安装的模块,不能通过
require()
加载使用。全局安装的模块,一般都是命令或者工具。
安装方法,在安装模块的命令后面,加
-g
npm i 模块名 -g
# 或
npm i -g 模块名</pre>
- 卸载方法(也是多一个
-g
)
npm un 模块名 -g</pre>
-
全局安装的模块,在系统盘(C盘)
- 通过命令
npm root -g
可以查看全局安装路径
- 通过命令
查看安装的全局模块----没有-g查看本地安装,加上-g查看全局模块
npm list -g --depth 0
全局安装nodemon模块
- 安装命令
npm i nodemon -g
nodemon的作用:
代替node命令,启动服务的,当更改代码之后,nodemon会自动帮我们重启服务。
运行nodemon,如果报错如下:
[图片上传失败...(image-2a0f9e-1609946235846)]
-
解决办法是:
管理员
方式,打开命令行窗口执行
set-ExecutionPolicy RemoteSigned;
在出现的选项中,输入
A
,回车。即可
执行 : nodemon 文件路径
更改镜像源
镜像源,就是下载安装第三方模块的网站。
我们下载的第三方模块都是从国外的npm主站下载的,速度比较慢。
淘宝在国内对npm上的第三方模块做了一个备份,也就是说,我们可以从国内下载第三方模块。
除了淘宝之外,还有很多其他镜像源。
简单的更改镜像源方法:
-
全局安装 nrm 的模块
- nrm 用于管理镜像源
-
使用nrm
nrm ls
通过这个命令,可以查看可用的镜像源nrm use taobao
,切换下载模块的网站为淘宝
模块化
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。 对于整个系统来说,模块是可组合、分解和更换的单元。
编程中的模块化
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块。
把代码进行模块化拆分的好处:
提高了代码的复用性
提高了代码的可维护性
可以实现按需加载
文件作用域
-
通信规则
加载require
导出
Node中的模块分类:
Node.js 中根据模块来源的不同,将模块分为了 3 大类,分别是:
内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http 等)
自定义模块(用户创建的每个
.js
文件,都是自定义模块)第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
CommonJS规范
在node中的JavaScript有一个很重要的概念,系统模块
Node.js 遵循了 CommonJS 模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖。
CommonJS 规定:
模块作用域
每个模块内部,module 变量代表当前模块。
使用require() 方法用于加载模块
module 变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口。使用exports接口对象导出模块中的成员
加载某个模块,其实是加载该模块的 module.exports 属性。
require加载自定义模块
语法演示:
// 加载自定义模块
const 自定义变量名 = require('./custom');</pre>
作用:
执行被加载的模块中的代码
得到被加载模块中的
exports
导出接口对象
注意事项:
- 加载自定义的模块,需要加
./路径
,而且可以省略后缀.js
exports导出自定义模块
node中是模块作用域,默认文件中所有的成员只能在当前模块中有效,另一个JS文件就无法使用当前模块定义的内容所以需要导出导入文件
每个模块内部都有一个module对象。在module对象中有一个成员叫exports,也是对象。谁require,谁就得到
module.exports
属性,默认是一个空对象。对于希望可以被其他模块访问的成员,只需要把成员挂载到module。使用
module.exports
导出需要共享的内容。导出等于是给其赋值,重复赋值会被覆盖。
使用模块的JS文件需要使用
require()
导入模块。导入的内容就是,模块导出的内容
导出多个成员(必须在对象中)
exports.a = 123;
exports.b = 'hello';
exports.c = function(){
console.log('ccc')
}
exports.d = {
foo:'bar'
}</pre>
导出单个成员(拿到的就是函数、字符串)
module.exports = 'hello'
//以这个为准,后者会覆盖前者
module.exports = funciton(){
return x+y
}
//这样可以导出多个成员
module.exports{
add:function(){
return console.log(x+y)
},
str:'hello'
}</pre>
原理解析
- 在node底层中,每个模块都有一个自己的module对象,该module对象中,有一个成员叫exports,也是一个对象
//演示:
var module= {
exports:{
}
}
//如果需要对外导出某些成员,只需要把这些成员挂载到module对象上的exports对象中。
module.exports.foo = 'bar'//等于是在exports对象中添加了 foo: 'bar'
//默认在代码的最后有一句,谁来require,谁就得到module.exports
return module.exports
</pre>
- exports是
module.exports
的一个引用var exports = module.exports
//我们发现,每次导出接口的成员的时候,都需要通过module.exports.xxx=xxx的方式很麻烦
//于是,node为了简化操作,专门提供一个变量 var exports = module.exports
console.log( exports === module.exports) //true 可以使用任何一方来导出接口成员
//二者等价.最后return的是 module.exports 所以注意不要给exports重新赋值
module.exports.foo = 'bar'//等于是在exports对象中添加了 foo: 'bar'
exports.foo = 'bar'</pre>
模块加载顺序和区别
通过引入的内容 核心模块和第三方模块直接引入模块名,自定义模块必须要带有路径。
// 加载核心模块
const fs = require('fs');
// 加载第三方模块
const express = require('express');
// 加载自定义模块
const custom = require('./custom');</pre>
加载顺序:
无论是什么模块,我们都要使用
require()
去加载,然后才能使用。优先加载内置模块,即使有同名文件,也会优先使用内置模块
不是内置模块,先去缓存中找,缓存没有去找对应路径的文件
不存在对应的文件,就将这个路径作为文件夹加载。
对应的文件和文件夹还找不到就去
node_modules
下面找
注意事项:
加载自定义的模块,需要加
require(./路径)
,可以省略文件扩展名加载第三方模块和核心模块。只需要写
require(模块名)
如果是非路径形式的模块标识,会判断是不是核心模块,如果是,优先加载核心模块
-
如果是路径形式的。肯定是第三方模块,会去当前的
node_modules
文件中查找优先加载相同名字的文件,加载一个叫做 abc 的文件
自动补
.js
后缀,然后加载abc.js
文件自动补
.json
后缀,然后加载abc.json
文件自动补
.node
后缀,然后加载abc.node
文件以上文件都没有,则报错
Cannot find module './abc'
其他
main说明
package.json文件中的main选项,作用时配置路口文件,在路口文件中坑定有导出(module.express)
如果没有main选项,那么项目根目录必然会有index.js,默认是入口文件。
依赖管理dependencies:
nodejs 中总共有 5 种依赖:
dependencies (常用)
devDependencies (常用)
peerDependencies (不太常用)
bundledDependencies (我之前没用过)
optionalDependencies (我之前没用过)
dependencies:
保存本地安装的所有依赖
这是 npm 最基本的依赖,通过命令 npm i xxx -S
或者 npm i xxx --save
来安装一个包,并且添加到 package.json 的 dependencies 里面(这里 i
是 install
的简写,两者均可)。
如果直接只写一个包的名字,则安装当前 npm registry 中这个包的最新版本;如果要指定版本的,可以把版本号写在包名后面,例如 npm i webpack@3.0.0 --save
。
npm install
也支持 tag,tar 包地址等等,不过那些不太常用,可以查看官方文档。
dependencies 比较简单,我就不再多做解释了。注意一点:npm 5.x 开始可以省略 --save
,即如果执行 npm install xxx
,npm 一样会把包的依赖添加到 package.json 中去。要关闭这个功能,可以使用 npm config set save false
。
npm install
把逻辑代码pull到本地之后,通过npm install拉取到node_modules文件夹。依赖管理。一定要初始化,要有package.json文件
Express
介绍
Express 是一个第三方模块,用于快速搭建服务器
Express 是一个基于 Node.js 平台,快速、开放、极简的 web 开发框架。
express保留了http模块的基本API,使用express的时候,也能使用http的API
express还额外封装了一些新方法,能让我们更方便的搭建服务器
安装express
项目文件夹中,执行npm i express
即可下载安装express。
注意:express不能安装在express文件夹中。否则安装失败。
使用express搭建web服务器
步骤:
加载express模块
创建express服务器
开启服务器,设置端口
监听浏览器的请求并进行处理
代码演示:
// 1、加载express模块
const express = require('espress')
// 2、创建express服务器
const app = express()
// 3、设置端口、开启服务器
app.listen(8001, () => console.log('开启服务器'))
// 4、监听浏览请请求并处理
app.get('GET请求的地址', 处理函数)
app.post('POST请求的地址', 处理函数);</pre>
express封装的新方法
express之所以能够实现web服务器的搭建,是因为其内部对核心模块http进行了封装。提供一些非常好用的新方法。http方法也能使用。
-
req
获取POST请求体
req.body
获取GET请求参数(查询字符串格式)
req.query
获取GET请求动态参数(动态路由)
req.params
其他...
-
res
res.sendFile(文件的绝对路径)
-- 读取文件,并将结果响应。后面不要有res.send()
res.set({name, value})
-- 设置响应头res.status(200)
-- 设置响应状态码res.send(字符串或对象)
-- 响应结果。end()
和字符集效果res.json(对象)
-- 以JSON格式响应结果res.jsonp() -- 以JSONP格式响应结果
其他...
-
app
app.get()
-- 处理客户 端的GET请求app.post()
-- 处理客户端的POST请求app.use()
-- 设置应用级别的配置其他...
-
express
express.static() -- 开放静态资源
express.urlencoded() -- 获取POST请求体
其他...
GET接口
app.get('请求的URL', callback);
查询字符串 常规参数
?id=10&name=lw
获取参数方式:
res.query
代码演示
// 写接口
app.get('/index', (req, res) => {
console.log(req.query); // { id: '3', bookname: 'zxx', age: '20' }
});</pre>
动态参数(动态路由)
url/:id/:name
获取参数方式
res.params
代码演示
// /index/:id/:name 接口 动态参数
// 浏览器的请求:http://locallhost:3001/index1/20/ww
app.get('/index1/:id/:name', (req, res) => {
console.log(req.params) //{ id: '20', name: 'ww' } 可以获取所有动态参数
res.send()
})</pre>
-
匹配到所有的GET请求-配置404
-
app.get('*', (req, res) => {})
他能够匹配到所有的GET请求,所以把它放到所有接口的最后。
-
POST接口
app.post('请求的URL', callback)
获取POST请求体
GET没有请求体。POST方式才是才有请求体
请求体,即客户端提交的数据
可以使用http模块中的方法,获取请求体
-
POST请求体,有哪些格式
查询字符串 -- 对应的
Content-Type: application/x-www-form-urlencoded
FormData对象 -- 对应的
Content-Type: multipart/form-data; --XXADFsdfssf
请求体是查询字符串
const path = require('path')
const express = require('express')
const app = express()
app.listen(8001, () => console.log('开启服务器'))
// 全局应用级配置
//可以帮我们接收 content-type: application/x-www-form-urlencoded类型的请求体
app.use(express.urlencoded({ extended: false }))
app.post('/index', (req, res) => {
// 获取post的请求体 请求体是查询字符串
// 配置之后,任何一个POST接口,都可以通过req.body获取到请求体的内容
console.log(req.body) //[Object: null prototype] { name: 'zs', age: '20', id: '10' }
res.send()
})</pre>
postman发送一个POST方式的请求,来配合测试:
点击POST,选中body,选中x-www-formurlencoded。模拟发送post请求
请求体是FormData对象
需要使用第三方模块(multer)才能够获取到。
案例:图书接口
使用cors模块,实现跨资源共享 允许跨域 1、npm i cors 2、加载 const cors = require('cors) 3、app.use(cors())
使用cors模块,实现跨资源共享 允许跨域
1、npm i cors
2、加载 const cors = require('cors)
3、app.use(cors())
const cors = require('cors')
const fs = require('fs')
const path = require('path')
const express = require('express')
const app = express()
app.listen(3006, () => console.log('开启服务器'))
// 接收post请求的 查询字符串参数 req.body
app.use(express.urlencoded({ extended: false }))
// 通过应用级的配置,设置接口可以跨域
// app.use((req, res, next) => {
// res.set({
// 'Access-Control-Allow-Origin': '*',
// })
// next()
// })
// cors 的第三方模块 实现跨域
app.use(cors())
// 获取图书列表路由配置
app.get('/api/getbooks', (req, res) => {
// 获取图书列表文件
let data = require(path.join(__dirname, './books.json'))
res.json({
status: 200,
msg: '列表接口读取成功',
data: data,
})
})
// 添加图书
app.post('/api/addbook', (req, res) => {
// 获取参数
req.body.id = Date.now() //使用时间戳做id
// 获取图书列表文件
let data = require(path.join(__dirname, './books.json'))
// 把获取到的参数添加到图书列表文件中
data.push(req.body)
// 写入数据
fs.writeFile(
path.join(__dirname, './books.json'),
JSON.stringify(data, null, 2),
(err) => {
if (err) {
res.json({
status: 500,
msg: '添加图书失败',
})
} else {
res.json({
status: 201,
msg: '添加图书成功',
})
}
}
)
})
// 删除图书
app.get('/api/delbook', (req, res) => {
// 2、读取数据文件内容
// 3、删除id对应数据项
// 4、向数据文件写入新数据
// 1、拿到id
let id = req.query.id //拿到get请求 静态数据id
// 2、验证id 找不到或者不规范的时候
if (!id) {
res.json({
status: 500,
msg: '未指定要删除的图书Id',
})
return
}
// 拿到文件数据
let data = require(path.join(__dirname, './books.json'))
// 筛选数据,将选中的id删除
data = data.filter((item) => item.id != id)
// 写入数据
fs.writeFile(
path.join(__dirname, './books.json'),
JSON.stringify(data, null, 2),
(err) => {
if (err) {
res.json({
status: 500,
msg: '删除图书失败!',
})
} else {
res.json({
status: 200,
msg: '删除图书成功!',
})
}
}
)
})
</pre>
使用第三方模块,实现跨域资源共享
实现跨域资源共享,可以使用一个叫做 cors 的第三方模块。推荐使用它来实现跨域资源共享。
使用方法:
下载安装cors
npm i cors
const cors = require('cors');
--- 加载模块app.use(cors());
-- 使用use方法即可
开放静态资源
什么是静态资源:CSS文件、图片文件、JS文件等等
开放静态资源:开放出来,使客户端能够访问
-
具体做法:
比如,允许客户端访问某文件夹中的文件
app.use(express.static('绝对路径'))
d通过应用级配置
【注】如果配置多个静态资源目录有同名,会按照顺序显示。
配置一个别名,可以用来标识目录app.use('/别名',express.static('绝对路径'))
通过别名访问,互不干扰
接收POST请求体
-
POST请求体的类型(Content-Type)
application/x-www-form-urlencoded 比如:id=1&name=zs&age=20
form-data 比如,提交的是FormData对象
application/json 比如,提交的是 {"id": 1, "name": "zs", "age": 20}
其他...
-
服务器端接收不同类型的请求体,使用的方式是不同的
urlencoded --->
app.use(express.urlencoded({extended: false}));
application/json --->
app.use(express.json());
-- 没有演示form-data ---> 服务器端使用第三方模块处理(
multer
)
当初学习ajax的时候,如果是POST请求,为什么要加Content-Type
路由
express中的路由
指的是客户端的请求与服务器处理函数之间的映射关系。
Express 中的路由分 3 部分组成,分别是请求的类型、请求的 URL 地址、处理函数,格式如下
// 路径 ,就是我们之前说的接口的处理程序
app.get('/api/getbooks', (req, res) => {
});
app.post('/api/getbooks', (req, res) => {
});
app.post('/api/addbook', (req, res) => {
});</pre>
每当一个请求到达以后,都需要先经过路由的配置,只有匹配成功之后,才会调用对应的处理函数。
在匹配的时候,会按照路由的顺序进行匹配,如果请求的URL和请求的方式同时匹配成功,则Express会将这次的请求,转交给对应function函数进行处理。
模块化路由
为了方便对路由进行模块化管理。Express不建议直接将路由挂载到app上面运行,而是推荐将路由抽离出来成为单独的模块。抽离的步骤如下:
-
创建路由对应的.js文件:
创建router.js 存放 登录、注册、验证码三个路由
引入express模块,
const express = require('express');
- 调用express.Router()函数创建路由对象。路由对象router中会自动携带req、res。不用额外传递
const router = express.Router();
- 向路由对象上挂载具体的路由--配置路由。路由对象叫啥,下面就叫啥。不要写app了。
// 把app换成router,比如
router.get('/xxx/xxx', (req, res) => {});
router.post('/xxx/xxx', (req, res) => {});</pre>
-
导出路由对象,使用
nodule.express
向外共享路由文件module.exports = router;
-
在主文件中引入路由文件
const router = require('./router.js')
在主文件中使用路由
app.use(router)
// app.js 中,将路由导入,注册路由
const login = require('./router/logon.js');
app.use(login)
// app.use(require('./router/heroes.js'));
app.use( require(path.join(__dirname, 'router', 'heores.js')) );</pre>
为路由模块添加前缀
路由模块化之后,可以按照须有拆分成多个路由文件。每个被拆分的文件都要有引入创建导出
我们可以省略路由模块中的 /api
前缀,而是在注册路由的时候,统一设置。路由文件中,把前缀 /api 和 /my 去掉
// 导入路由模块,并注册路由
app.use('/api', require(path.join(__dirname, 'router', 'login.js')) );
app.use('/my', require(path.join(__dirname, 'router', 'heroes.js')) );</pre>
使用路由模块的好处
分模块管理路径,提高了代码的可读性
可维护性更强
减少路由的匹配次数
权限管理更方便
etc...
其他:
throw err是js中的语法。抛出语句异常
作用:
1、把错误的信息打到控制台
2、阻止程序的运行