前端基础知识---10 Node.js(二)
10.5 模块化
10.5.1模块化:把大文件拆分为多个独立且相互依赖的小文件
10.5.2模块分类:

10.5.3模块加载:require()

只有加载自定义模块的时候要用路径(可省略后缀名)
10.5.4模块的作用域
在模块内部的变量,外界无法访问(避免污染全局变量)

10.5.5向外共享模块作用域中的成员
module对象
module.exports对象:将模块内的成员共享出去,供外界使用。在外界用require()方法导入一个自定义模块的时候得到的成员就是模块中通过module.exports指向的那个对象。
在一个自定义模块中,默认 module.exports = {} //空对象 或 exports
最终共享的结果以module.exports指向的对象为准
(当其中一个是对象的时候才可能会被覆盖)



10.5.6 Node.js模块化规范CommonJS

10.6 包
包:第三方模块叫包。(基于内置模块封装出来的,提供了更高级更方便的API)
![]()
搜索包:npm | Home
先初始化jason:
npm init -y
安装包命令: npm i 包的完整名字


包的语义化版本规范;(例:2.30.1)
(1)大版本(底层)
(2)功能版本
(3)Bug修复版本
10.6.1 包管理配置文件
共享资源注意:
(1)上传时要把node_modules文件夹添加到.gitignore中
(2)在根目录创建一个package.json文件记录项目中所安装的包
npm init -y
(项目名称为英文!且不能出现空格!)
安装包后会有dependencies对象记录包(属性)的信息
一次性安装所有的包: npm install
卸载包:npm uninstall 包的名字
只在项目开发阶段使用的包:npm i 包的名字 -D
项目开发和上线之后都用得到的,记录在dependencies中: npm i 包的名字
解决下包速度慢的问题:
镜像:一种文件存储形式,一个磁盘在另一个磁盘上存在一个完全相同的副本

安装淘宝镜像源
(1)查看当前下包镜像源:npm config get registry
(2)切换为淘宝镜像源:npm config set registry=https://registry.npm.taobao.org/
(3)查看是否下载成功:npm config get registry
切换下包镜像源:
(1)安装nrm工具:npm install -g nrm
(2)查看所有可用的镜像源:nrm ls

(3)切换为淘宝镜像资源:nrm use taobao

10.6.3包的分类
(1)全局包 -g
i5ting_toc 可以把md文件转为html文件
10.6.4规范的包结构

(1)初始化包的基本结构
{
"name":"itTools", //名字不能重复
"version":"1.0.0", //版本号
"main":"index.js", //程序入口
"description": "提供了格式化时间、HTML、escape相关功能", //相关描述
"keywords": ["itTools","dateFormat","escape"], //搜索关键词
"license":"ISC" //此包所遵循的许可证
}
(2)定义格式化的时间函数并暴露在外
//定义格式化的时间函数
function dataFormat(dataStr){
const dt = new Date(dataStr)
const y = dt.getFullYear()
const m = padZero(dt.getMonth() +1)
const d = padZero(dt.getDate())
const hh = padZero(dt.getHours())
const mm = padZero(dt.getMinutes())
const ss = padZero(dt.getSeconds())
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
function padZero(n){
return n > 9 ? n : '0'+n
}
module.exports = {
dataFormat
}
(3)转义、还原html的方法
/g表示全局搜索
//转义html的方法
function htmlEscape(htmlStr){
return htmlStr.replace(/<|>|"|&/g, (match)=>{
switch(match){
case'<':
return '<'
case'>':
return '>'
case'"':
return '"'
case'&':
return '&'
}
})
}

(4)将不同的功能进行模块化拆分

const data = require('./src/dataFormat')
const escape = require('./src/htmlFormat')
//向外暴露需要的成员
MediaSourceHandle.exports = {
...data,
...escape //...展开属性
}
(5)编写包的说明文档

(6)发布包
1.在终端登录
npm login --auth-type=legacy
2.发布包
npm publish
3.删除包
npm unpublish 包名 --force
10.6.5模块的加载机制
(1)模块优先被缓存加载
(2)内置模块加载优先级最高
(3)自定义模块加载的时候要用./或../路径标识符

(4)目录加载模式

10.7 express
10.7.7express简介
Express是基于Node.js平台,快速、开放、极简的Web开发框架(用于创建Web服务器)
Express是基于http内置模块封装出来的(类似于Web API和jQuery,后者是基于前者进一步封装得来的)
Express可以更方便快捷创建Web网站的服务器和API接口的服务器
10.7.2创建一个web服务器
首先安装express npm i express
//1.导入express
const express = require('express')
//2.创建web服务器
const app = express()
//3.启动web服务器
app.listen(80,()=>{
console.log("express sever running at http://127.0.0.1")
})
10.7.3express基本使用
(1)app.get() 监听GET请求
(2)app.post() 监听POST请求
(3)res.send() 向客户端响应JSON对象
(4)req.query 查询url中携带的参数
(5)req.params 获取url中的动态参数
//4.监听客户端的GET和POST请求,并向客户端响应具体内容
app.get('/user',(req,res)=>{
//调用express中的res.send()方法,向客户端响应一个JSON对象
res.send({name:"张三",age:20,gender:"男"})
})
app.post('/user',(req,res)=>{
//调用express中的res.send()方法,向客户端响应一个JSON对象
res.send('请求成功')
})
//5.获取url中携带的查询参数
app.get('/',(req,res)=>{
console.log(req.query)
res.send(req.query)
})
//6.获取url中的动态参数
app.get('/user/:id/:name',(req,res)=>{
console.log(req.params)
res.send(req.params)
})
GET和POST请求的区别:Get 和 Post 的区别:通俗易懂_get和post请求的区别-CSDN博客
1、参数传递方式不同
Get 请求的参数附加在 URL 末尾,多个参数用 & 分隔。
Post 请求的参数放在请求体中传输。
2、安全性和隐私性不同
Get 请求的参数直接暴露在 URL 中,不安全也缺乏隐私性。
Post 请求的参数在请求体中,相对更加安全和隐蔽。
3、传输数据量的限制不同
Get 请求受限于 URL 的最大长度(通常是 2048 个字符),无法传输大量数据。
Post 请求的请求体大小没有限制,可以传输任意量的数据。
4、幂等性不同
Get 请求是幂等的,多次请求得到的结果是相同的。
Post 请求默认是非幂等的,多次请求可能会创建多个资源或产生不同结果。
5、可缓存性不同
Get 请求的响应可以被浏览器缓存,下次请求时直接使用缓存数据。
Post 请求的响应默认不会被浏览器缓存。
6、书签和历史记录支持度不同
Get 请求的 URL 可以被加入书签,请求参数会被保留。
Post 请求的参数不会被保存在书签或浏览器历史记录中。
在选择使用 Post 还是 Get 请求时,可以遵循以下一些原则:
如果是获取资源,并且没有修改服务器数据,使用 Get 请求。
如果是向服务器提交数据,或者创建、更新资源,使用 Post 请求。
如果参数包含敏感信息(如密码),或者数据量较大,使用 Post 请求。
如果要支持 URL 收藏和分享,使用 Get 请求。

10.7.4静态资源服务器 express.static()
静态资源服务器的核心是对外提供静态文件(如 HTML、CSS、图片等)的访问服务,但 “是否能被外部使用”,取决于部署方式
const express = require('express') //导入express
const app = express() //创建web服务器
//调用express.static()方法,快速对外提供静态资源
app.use(express.static('./clock'))
app.listen(80,()=>{
console.log('express server running at http://127.0.0.1')
})
托管多个静态资源目录:多次调用即可。不过先写的优先被调用

添加前路径:app.use('/abc',express.static('./clock'))
10.7.6nodemon自动重启项目
npm i -g nodemon 安装命令
nodemon .\test2.js 终端运行
10.8 路由
路由:按键与服务之间的关系
express中的路由:客户端的请求与服务器处理函数之间的映射关系
express的路由(请求类型,请求的url地址,处理函数)

10.8.1路由的概念
路由匹配过程:每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功才会调用对应的处理函数。(按顺序匹配,请求类型和请求的url同时匹配成功,才会将请求交给对应的function函数进行处理)

10.8.2模块化路由

10.9 中间件
10.9.1 express中间件的调用方式

10.9.2 express中间件的格式
中间件包含next参数(表示把流转关系转交给下一个中间件或路由)
而路由只包含req和res

10.9.3 中间件的使用
作用:多个中间件之间,共享同一份req和res。基于此特性,可在上游中间件中,统一为req和res添加自定义属性和方法,供下游的中间件或路由使用
(1)全局中间件 app.use()
定义多个全局中间件就多次调用app.use(),按先后顺序依次调用
const express = require('express')
const app = express()
//定于一个最简单的中间件函数
const mw = function(req,res,next){
//获取到达服务器的时间
const time = Date.now()
//为req对象挂载自定义属性,从而将时间共享给后面的所有路由
req.startTime = time
//把流转关系转交给下一个中间件或路由
next()
}
//将mw注册为全局生效的中间件
app.use(mw)
//定义路由
app.get('/user',(req,res)=>{
res.send('Hello user!'+req.startTime)
})
app.get('/users',(req,res)=>{
res.send('Good night user!'+req.startTime)
})
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
(2)局部生效的中间件
不使用app.use()定义的中间件

10.9.4中间件的使用注意事项

10.9.5 中间件的分类
(1)应用型
(2)路由型
(3)错误型(err,req,res,next)
一定要把它注册在所有路由之后!!!

(4)内置中间件
默认情况下如果不配置中间件,则req.body默认为undefined

2)express.json()
//除错误级别的中间件,其他的中间件必须在路由之前进行配置
app.use(express.json())
app.post('/user',(req,res)=>{
res.send({
message: '成功收到 JSON',
data: req.body // 把收到的 JSON 再返回给前端
})
(5)第三方的中间件

10.9.6自定义中间件

第一个js文件(中间件)
//导入模块解析字符串
const qs = require('querystring')
//这是解析表单数据的中间件
const bodyParser = ((req,res,next)=>{
let str = ''
req.on('data',(chunk)=>{
str += chunk//数据量较大的话,客户端会把数据切割后分批发送到服务器。因此这里需要数据拼接
})
req.on('end',()=>{
const body = qs.parse(str) //把字符串格式的请求体数据,解析成对象格式
req.body = body //将解析出来的对象挂载为req.body
next()
})
})
module.exports= bodyParser
第二个js文件
const express = require('express')
const app =express()
//1.导入自己封装的中间件模块
const customBodyParser = require('./custom-body-parser')
//2.将自定义的中间件函数,注册为全局可用的中间件
app.use(customBodyParser)
//定义路由
app.post('/user',(req,res)=>{
res.send(req.body)
})
app.listen(80,()=>{
console.log("http://127.0.0.1")
})
10.10 接口
接口:为了体现实物功能的扩展性,java提供了借口来定义这些额外的功能,在接口中不给出具体的实现。
你可以把「接口」理解为 “前端和后端之间的 “沟通桥梁””:
- 前端需要数据(比如用户列表、商品信息),就通过接口 “问” 后端要;
- 前端需要提交数据(比如注册表单、提交订单),就通过接口 “给” 后端送;
- 接口的本质是「HTTP 请求 + 后端处理逻辑 + HTTP 响应」的组合,你需要先明白 “请求发什么、后端怎么接、响应回什么”。


API接口的调用,一般有两种请求的方法,get方法和post方法。
get方法通常用来查询数据,post方法通常用来修改数据。
10.10.1 编写get,post接口
(1)编写路由模块get,post接口js文件(使用express导入模块,挂载路由,导出模块)
const express = require('express')
const router = express.Router()
//在这里挂载对应的路由
router.get('/get',(req,res)=>{
//获取客户端通过查询字符串,发送到服务器的数据
const query = req.query
res.send({
status:0,//0表示处理成功,1表示处理失败
msg:'GET请求成功!',
data:query //需要响应给客户端的数据
})
})
//定义POST接口
router.post('/post',(req,res)=>{
//注意!!!调用res.body获取请求体中包含的url-encoded格式的数据
const body = req.body
res.send({
status:0,
msg:'POST请求成功',
data:body
})
})
module.exports = router
(2)调用get接口(创建基本服务器,导入路由模块,注册到app上)
调用res.body获取请求体中包含的url-encoded格式的数据
const express = require('express')
const app = express()
//配置解析表单数据的中间件
app.use(express.urlencoded({extended:false}))
//导入路由模块
const router = require('./apiRouter')
//把路由模块,注册到app上
app.use('/api',router)
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
10.10.2 基于cors解决接口跨域问题
CORS:由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否组织前端JS代码跨域获取资源


一定要在路由之前,配置cors中间件,从而解决接口跨域的问题

10.10.3 CORS 的三个响应头
(1)origin 允许其他域的访问

(2)Headers 对超过9个的额外请求头进行声明

(3)Methods 支持使用除GET/POST/HEAD以外的其他请求方法

10.10.4 CORS的请求分类
(1)简单请求
客户端与服务器只会发生一次请求

(2)预检请求
客户端与服务器会发生两次请求。OPTION预检请求成功之后,才会发起真正的请求。

10.10.5 JSONP接口
JSONP概念:浏览器通过<script>标签的src属性,请求服务器上的数据,同时返回一个函数的调用。这种请求方式就叫做JSONP。
特点:
(1)JSONP不属于Ajax请求
(2)仅支持GET请求
注意:如果项目中已经配置了CORS跨域资源共享,为防止冲突,必须在配置CORS中间件之前声明JSONP的接口。
实现JSONP接口的步骤:


更多推荐
所有评论(0)