[前端学习笔记]Node.js基础知识整理(包含npm、express、cors、mysql)

文章目录

      • 一、什么是Node.js
        • 1. Node.js运行环境
        • 2. Node.js可以做什么
      • 二、Node.js内置API模块
        • 1. fs模块:读写操作文件
        • 2. path模块:处理路径
        • 3. http模块:创建web服务器
      • 三、模块化与npm
        • 1. 模块化
        • 2. npm
      • 四、Node.js第三方API模块
        • 1. express
        • 2. CORS
        • 3. mysql
      • 五、Web开发模式
      • 六、身份认证
        • 1. Session认证机制
        • 2. JWT认证机制
      • 七、补充
        • 1. 对密码进行加密处理
        • 2. 验证表单数据的合法性

一、什么是Node.js

Node.js是一个基于"Chrome V8"JS解析引擎的JS运行环境。官网

1. Node.js运行环境

[前端学习笔记]Node.js基础知识整理(包含npm、express、cors、mysql)_第1张图片

浏览器是JS的前端运行环境;Node.js是JS的后端运行环境。

2. Node.js可以做什么

  • 基于Express框架,可以构建Web应用
  • 基于Electron框架,可以构建跨平台的桌面应用
  • 基于restify框架,可以构建API接口项目
  • 读写和操作数据库,创建实用的命令行工具辅助前端开发,etc…

二、Node.js内置API模块

内置API是由运行环境提供的特殊接口,只能在所属运行环境中被调用。

1. fs模块:读写操作文件

// 导入fs模块
// require()方法加载模块时,会执行被加载模块中的代码
const fs = require('fs')

// 读取指定文件[path存放路径;option编码格式(一般'utf8')]
fs.readFile(path, [option], function(err, dataStr) {
	// 失败的结果
	console.log(err)
  	// 成功的内容
  	console.log(dataStr)
})

// 写入指定文件[path存放路径;data写入的内容;option编码格式(一般'utf8')]
fs.writeFile(path, data, [option], function (err) {
	if (err) {
    	return console.log('文件写入失败!' + err.message)
  	}
  	console.log('文件写入成功!')
})

2. path模块:处理路径

路径path使用相对路径容易出现“路径动态拼接错误”的问题,代码会以执行node命令的目录为当前目录。提供完整路径可以解决此问题。

// 导入path模块
const path = require('path')

// 拼接路径[__dirname表示当前文件所处的目录]
path.join(path1, path2, ...)

// 获取路径中的文件名(ext可以获得去除扩展名的文件名)
const fpath = '/a/b/c/index.html'
path.basename(fpath,[ext])
// 获取路径中的扩展名
path.extname(fpath)

3. http模块:创建web服务器

1)服务器基础知识

  • IP地址:互联网每台计算机的唯一地址,用点分十进制表示。通过ping命令可以查看服务器的IP地址。
  • 域名:和IP地址一一对应的关系,对应关系存放在域名服务器(DNS)中。
  • 域名服务器:提供IP地址和域名之间转换服务的服务器。
  • 端口:标识web服务,每个web服务都对应一个唯一的端口号。客户端发送的请求通过端口号准确交给对应的web服务器进行处理。

2)http模块

// 导入http模块
const http = require('http')
// 创建web服务器实例
const server = http.createServer()
// 为服务器绑定request事件监听客户端请求
server.on('request', (req, res)=>{
	// req.url		客户端请求的URL地址
	// req.method  	客户端请求的method类型
	// res.end		向客户端响应的内容
	// 设置Content-Type响应头,解决中文乱码的问题
	res.setHeader('Content-Type','text/html; charset=utf-8') 
})
// 启动web服务器
server.listen(80,()=>{ 
	console.log('server running at http://127.0.0.1')
})

三、模块化与npm

1. 模块化

1)模块化概念
解决复杂问题时,自顶向下逐层把系统划分成若干模块的过程。把一个大文件拆成独立并相互依赖的多个小模块,模块是可组合、分解和更换的单元。提高了代码的复用性、可维护性,可以实现按需加载。

2)模块化规范
对代码进行模块化的拆分和组合时需要遵循的规则。降低沟通成本,极大方便了各个模块之间的相互调用。Node.js遵循CommonJS模版规范:

  • 每个模版内部,model变量代表当前模块。
  • module变量是一个对象,module.exports是对外的接口。
  • require加载模块,加载模块的module.exports属性。

3)Node.js中模块分类

  • 内置模块:Node.js官方提供的
  • 自定义模块:用户自创建的js文件
  • 第三方模块:由第三方开发出来的

4)模块作用域
在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问。防止了全局变量污染问题,通过module对象向外共享模块作用域中的成员,外界使用require方法导入自定义模块时得到modules.exports所指向的对象。Node提供exports对象与modules.exports指向同一个对象。

2. npm

1)包
包是由第三方基于内置模块开发出来,提供更高级、方便的API,免费供所有人使用,极大的提高了开发效率。

  • 可以从https://www.npmjs.com网站搜索需要的包,从https://registry.npmjs.org服务器下载需要的包。
  • 包可以分为项目包和全局包。项目包安装到项目的node_modules目录下,全局包安装到用户node_modules目录下。
  • 规范的包结构:
    1—包必须以单独的目录存在。
    2—包的顶级目录下必须包含package.json包管理配置文件,记录项目相关的配置信息。其中dependencies节点中记录安装了哪些包。
    3—package.json中必须包含name包名、version版本号、main包的入口三个属性。
    4—package-lock.json中记录node_modules目录下每个包的下载信息。

2)npm
npm(Node Package Manager)包管理工具可以从上述服务器把需要的包下载到本地使用。npm随着Node.js自动安装。

3)npm常用命令

// 在执行命令目录中快速创建package.json文件
npm init -y
// 安装指定包[可以指定版本:大版本.功能版本.修复版本]
npm install/i 包名@版本号
// 安装全局包
npm install/i 包名 -g
// 一次性安装dependencies节点所有依赖包
npm install/i
// 安装指定包并记录在devDependencies节点
// 【开发依赖包】只在开发阶段用到,上线阶段不会用到的记录在devDependencies节点
// 【核心依赖包】开发阶段和上线阶段都用到的记录在dependencies节点
npm install/i 包名 -D
// 卸载指定包
npm uninstall 包名
// 监听项目文件,实现自动重启项目
nodemon 文件名
// 切换镜像服务器加快下载速度【不方便】
npm config get registry
npm config set registry=https://registry.npm.taobao.org/
// 通过nrm包切换镜像服务器【方便】
npm i nrm -g 
nrm ls
nrm use taobao

4)模块加载机制

  • 优先从缓存中加载模块。
  • 【内置模块】加载优先级最高;【自定义模块】需有路径标识符;【第三方模块】从node_modules文件夹加载。
  • 【没有写扩展名的模块】加载顺序为:按确切的文件名加载;补全.js扩展名加载;补全.json扩展名加载;补全.node扩展名加载;加载失败报错。
  • 【目录作为模块】加载顺序为:从目录下找package.json的main属性作为加载入口;上述不存在则尝试加载目录下的index.js文件;都失败则加载失败报错。

四、Node.js第三方API模块

1. express

1)express基本用法
express是基于Node.js平台,基于内置http模块进一步封装的专门用来创建Web服务器的Web开发框架。能够极大的提高开发服务器的效率。官网

// 创建Web网站服务器
const express = require('express')
const app = express()
// 监听GET请求
app.get('url',(req, res)=>{
	// 向客户端响应JSON对象
	res.send({name:'zs',age:20})
	// 向客户端响应文本字符串
	res.send('ok')
	// req.query获取客户端发送的查询参数,默认为空对象
	console.log(req.query)
	// req.params获取动态匹配的URL参数,默认为空对象
	console.log(req.params)
})
// 监听POST请求
app.post('url',(req, res)=>{
	// req.body获取解析后的请求体数据,默认为空对象
	console.log(req.body)
})
// 启动服务器
app.listen(端口号,()=>{})
// 创建静态资源服务器
// 对外提供upload目录下的内容,挂载路径前缀/upload
app.use('/upload', express.static('upload'))

2)express路由
在express中,路由指客户端的请求与服务端处理函数之间的映射关系。由请求类型、请求URL地址、处理函数三部分组成。
[前端学习笔记]Node.js基础知识整理(包含npm、express、cors、mysql)_第2张图片

// 把路由挂载到服务器上
app.get('/', (req, res)=>{
	res.send('Get Request')
})
app.post('/', (req, res)=>{
	res.send('Post Request')
})
// 模块化管理路由:路由写在单独的router.js文件,通过module.exports向外共享路由对象
const router = require('./router')
app.use('/api', router) // 可以添加访问前缀

3)express中间件
中间件(Middleware)指业务流程的中间处理环节。当请求到达express服务器后,可以连续调用多个中间件进行预处理,本质是function处理函数。

const mw = function(req, res, next){
	// 多个中间件之间共享一份req和res,按先后顺序依次调用
	// next() 实现多个中间件连续调用,把流转关系交给下一个中间件/路由
	next() 
}
  • 区分路由处理函数和中间件:中间件包含next参数
  • 中间件生效范围:全局生效/局部生效
// 全局中间件
app.use((req, res, next)=>{
	next()
})
// 局部中间件:mw1、mw2为已定义的中间件
app.get('/',[mw1, mw2], (req, res)=>{})
  • 中间件的分类【5类】

1—应用级别的中间件:绑定在服务器实例app上的中间件
2—路由级别的中间件:绑定在路由实例router上的中间件
3—错误级别的中间件:捕捉整个项目中发生的异常错误,防止项目异常崩溃

app.use((err, req, res, next)=>{
	res.send(err.message)
})

4—Express内置的中间件:

// 1. 托管静态资源-例如HTML文件、CSS文件、图片...
app.use(express.static('upload'))
// 2. 解析JSON格式的请求体数据,4.16.0版本以上可以
app.use(express.json())
// 3. 解析URL-encoded格式请求体数据,4.16.0版本以上可以
app.use(express.urlencoded({extended:false}))

5—第三方提供的中间件:

// 例如:body-parser 解析URL-encoded格式请求体数据
app.use(parser.urlencoded({extended:false}))

4)express接口
编写接口步骤如下:

  • 创建基本的服务器
  • 创建API路由模块
  • 编写GET/POST/DELETE接口
  • 基于CORS解决跨域请求问题

2. CORS

CORS(Cross-Origin Resource Sharing,跨域资源请求)是express的第三方中间件,可以方便的解决跨域请求问题。由一系列的HTTP响应头组成,这些响应头决定浏览器是否阻止跨域获得资源【浏览器的同源安全策略默认阻止跨域】
CORS只在服务器端进行配置,客户端浏览器无需进行任何额外配置。
CORS有兼容性问题,只有支持XMLHttpRequest Level2的浏览器支持。

1)CORS的基本使用

// 安装cors中间件
npm install cors
// 导入cors中间件
const cors = require('cors')
// 全局配置cors中间件[要在路由前调用]
app.use(cors())

2)CORS响应头部

// 指定允许访问该资源的外域URL
res.setHeader('Access-Control-Allow-Origin','https://www.baidu.com/')
// 对额外的请求头进行声明[默认仅支持9个:Accept\Accept-Language\Content-Language\DPR\Downlink\Save-Data\Viewport-Width\Width\Content-Type]
res.setHeader('Access-Control-Allow-Headers','...')
// 指定允许的HTTP请求方法
res.setHeader('Access-Control-Allow-Methods','POST,GET,DELETE,HRAD')

3)CORS请求分类:根据请求方法和请求头的不同进行划分

  • 简单请求:客户端与服务器之间只会发生一次请求
    请求方法为GET、POST、HEAD三者之一;请求头只有上述默认的9种。
  • 预检请求:客户端与服务器之间会发生两次请求(多了一个OPTION预检请求)
    请求方法或请求头是上述之外的;向服务器发送了application/json格式的数据。

3. mysql

1)数据库
数据库(database)是用来组织存储管理数据的仓库。

  • 数据库数据组织结构:数据库(database)、数据表(table)、数据行(row)、字段(field)
  • MySQL数据库:目前使用最广泛、流行度最高的开源免费数据库。其中,MySQL Server专门用来提供数据存储和服务;MySQL Workbench是可视化的MySQL管理工具。

2)SQL语句
SQL(Structured Query Language,结构化查询语言),是用来访问和处理数据库的编程语言。在关系型数据库中使用。

  • 增删改查基本操作
// 查
select * from users;
select username, password from users;
// 增
insert into users(username, password) values ('tony','123456');
// 改
update users set password='000000',status=1 where id=5;
// 删
delete from users where id=5;
  • where条件子句
操作符 描述
= 等于
<> 或 != 不等于
> 、<、>=、<= 大于、小于、大于等于、小于等于
BETWEEN 在某个范围内
LIKE 模糊搜索
AND 同时满足多个条件
OR 满足任意一个条件
  • order by根据指定的列对结果集排序
// 【默认,ASC可省略】升序ASC
select * from users order by id; 
// 降序DESC
select * from users order by id DESC; 
select * from users order by id DESC, username ASC; 
  • count(*)返回查询结果的总数据条数
// as 可以指定列名
select count(*) as total from users where status=0;

3)mysql模块

// 1. 安装第三方mysql模块
// 2. 连接到mysql数据库
const mysql = require('mysql')
const db = mysql.createPool({
	host:'127.0.0.1'
	user:'root'
	password:'111111'
	database:'mydata'
})
// 3. 执行sql语句操作数据库
// ? 作为占位符
const sql = 'select * from users where id=?'
db.query(sql,user.id,(res,results)=>{
	if(err) return console.log(err.message)
	console.log(results)
})
// set ? 传递参数的简便方式
const sql = 'update users set ? where id=?'
db.query(sql,[user,user.id],(err,results)=>{
	if(err) return console.log(err.message)
	if(results.affectedRows === 1){
		console.log('更新数据成功')
	}
})
// 为保险期间,删除数据时通过“标记删除”来模拟删除:设置修改status状态字段标记为删除

五、Web开发模式

目前主流的Web开发模式有两种:

1)基于服务器渲染的传统Web开发模式:服务器发送给客户端通过字符串拼接动态生成的HTML页面,客户端不需要额外请求页面数据。

  • 优点:前端耗时少;完整的HTML页面内容有利于SEO。
  • 缺点:占用服务器端资源;不利于前后端分工合作开发效率低。

2)基于前后端分离的新型Web开发模式:依赖于Ajax技术的广泛应用,后端只负责提供API接口,前端使用Ajax调用接口。

  • 优点:前后端分工合作;实现页面局部刷新提高用户体验;减轻了服务器端渲染压力。
  • 缺点:不利于SEO(利用前端框架提供的SSR技术可以解决)

六、身份认证

身份认证(Authentication)是通过一定的手段完成对用户身份的确认。不同的Web开发模式有不同的身份认证方式:

  • 服务端渲染推荐使用Session认证机制
  • 前后端分离推荐使用JWT认证机制

1. Session认证机制

[前端学习笔记]Node.js基础知识整理(包含npm、express、cors、mysql)_第3张图片

Session工作原理:在服务器端生成Cookie 保存在服务器,响应给客户端。客户端再次请求时,通过请求头自动将当前域名下的所有Cookie发送给服务器,服务器通过Cookie查找对应的用户信息进行身份认证。【Cookie是存储在用户浏览器中的一段字符串,由名称、值和用于控制有效期、安全性、使用范围的可选属性组成】

// 1. 安装express-session中间件
// 2. 配置express-session中间件
app.use(session({
	secret: 'cat',
	resave: false,
	saveUninitialized: true
}))
// 3. 登录成功后向session中存数据
req.session.user = req.body // 用户信息
req.session.islogin = true // 用户登录状态
// 4. 从session中取数据
if (!req.session islogin) {
	return res.send({ status:1 ,msg:'fail' })
}
res.send({ status:0 ,msg:'success',username:req.session.user.username })
// 5. 清空当前用户的session信息
req.session.destroy()

2. JWT认证机制

Session认证需要配合Cookie,但Cookie不支持跨域访问,需要额外的配置。需要跨域请求的可以使用JWT认证机制。

JWT(JSON Web Token)是目前最流行的跨域认证解决方案,用户信息通过加密后生成Token字符串保存在客户端浏览器上,服务端通过还原Token字符串的形式认证用户身份。
[前端学习笔记]Node.js基础知识整理(包含npm、express、cors、mysql)_第4张图片
JWT类型的Token由三部分组成:Header(头部).Payload(有效荷载).Signature(签名),其中,Payload是用户信息经过加密后生成的字符串;Header和Signature是安全性相关信息。

// 1. 安装JWT相关的包:jsonwebtoken和express-jwt
// 2. 导入JWT相关的包
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
// 3. 定义secret密钥:保证JWT的安全性,用于加密和解密
const secretKey = 'im sillyxue'
// 4. 登录成功后生成JWT字符串:不要把密码加密到Token
const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })
// 5. 将客户端通过请求头Authorization发送的Token解析成JSON对象
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))
// 当解析成功后,可以使用req.user获取解析到的用户信息
console.log(req.user)
// 6. 捕获解析失败错误:Token字符串过期/不合法会导致解析失败 UnauthorizedError
// 写在错误级别的中间件中
if (err.name === 'UnauthorizedError') {
    return res.send({
      status: 401,
      message: '无效的token',
    })
}

七、补充

1. 对密码进行加密处理

为了保证密码的安全性,不建议在数据库以明文的形式保存用户密码,推荐对密码进行加密存储。可以使用bcryptjs对用户密码进行加密:加密后的密码无法被逆向破解;同一明文密码多次加密的结果不同,保证了安全性。

// 导入bcryptjs
const bcrypt = require('bcryptjs')
// 对密码加密
userinfo.password = bcrypt.hashSync(明文密码,随机盐的长度)
// 判断密码是否一致[false表示密码错误]
const compareResult = bcrypt.compareSync(用户提交的密码,数据库中存储的密码)

2. 验证表单数据的合法性

单纯使用if验证数据合法性效率低下、出错率高、维护性差。使用第三方数据验证模块,可以降低出错率,提高验证的效率和可维护性。

1)非formdata格式请求体
使用@hapi/joi中间件定义验证规则:

const joi = require('@hapi/joi')
// 定义验证规则
const username = joi.string().alphanum().min(1).max(10).required()
const password = joi.string().pattern(/^[\S]{6,12}$/).required()
// 向外暴露
exports.reg_login_schema = {
	body:{username, password}
}

使用@escook/express-joi中间件自动对表单数据验证:

const expressJoi = require('@escook/express-joi')
// 导入验证对象
const {reg_login_schema} = require('../schema/user')
// 声明局部中间件进行数据验证
router.post('/reguser',expressJoi(reg_login_schema),userHandler.regUser)

在错误级别的中间件中间件中捕获验证错误:

if (err instanceof joi.ValidationError) res.send(err)

2)formdata格式请求体
以上中间件无法解析multipart/form-data格式的请求体数据,可以使用multer中间件。

const multer = require('multer')
// 创建multer实例对象,通过dest属性置顶文件的存放路径
const upload = multer({dest: path.join(__dirname,'../uploads')})
// 声明局部中间件解析formdata格式的表单数据
// 文本类型的挂载到req.body  文件类型的挂载到req.file
router.post('/add',upload.single('cover_img'),article_handler.addArticle)

你可能感兴趣的:(前端,前端,javascript,node.js)