处理表单提交数据
数组的归纳方法,返回最终归纳的值 arr.reduce
- 第一个参数是函数,这个函数会循环调用,数组有多少个元素,就会调用多少次
- 函数的第一个参数是当前归纳的值
- 函数的第二个参数是每次循环的循环项
- 注意:函数的返回值会作为下一次的归纳值
- 第二个参数是归纳的起始值
$('#loginForm').submit(() => {
let { email, password } = $('#loginForm').serializeArray().reduce((obj, v) => {
obj[v.name] = v.value
// 必须返回出来
return obj
}, {})
if (email.trim() === '' || password.trim() === '') {
alert('邮箱或密码不能为空')
return false; // 中断后面的代码 并且阻止表单的默认提交行为
}
})
HTTP协议的特点
- 无状态:是指协议对于事物处理没有记忆功能,也就是说,对于服务端来讲,他不关心客户端是谁,他只关心请求,请求来了服务端就响应,响应完了谁也不认识谁,这种特性严重阻碍了需要客户端与服务端进行动态交互的web应用程序的实现,所以呢,cookie和session这种用户保持HTTP连接状态的技术就应运而生了,就是为了解决这个缺陷的
cookie
cookie:通过客户端来保持状态的解决方案(供服务端存储数据)
- 以域名的形式进行区分
- 具体时效性,过期之后会被浏览器自动删除,如果你不设置过期时间,那么默认情况下会在关闭浏览器时删除
- 特别要注意:在发送请求的时候会自动携带到请求头中一并发送给服务端
- 交互流程:客户端请求服务端(携带请求数据) => 服务端响应客户端(在响应头中携带需要被客户端保存的cookie数据) => 客户端接收服务端响应(保存cookie数据,存盘,磁盘中) => 客户端再次发送请求的时候(自动在请求头中携带已有的cookie数据) => 服务端接收客户端请求(从请求头中获取cookie数据),后面的流程同上。。。
session
session:通过服务端来保持状态的解决方案(供客户端存储数据)
- 是服务端为客户端开辟的存储空间,在其中保存数据
- 也有时效性,服务端重启时会失效
- 很重的一点,他是基于cookie来实现的,会将生成的sessionId以cookie的形式保存在客户端中
- 交互流程:客户端请求服务端(携带请求数据) => 服务端接收请求(给你开辟一个存储空间,用来保存你的数据,实际上就是创建session,并为之生成一个唯一的id,也就是sessionId) => 服务端响应客户端(在响应头中携带包含sessionId的cookie数据) => 客户端接收响应(从响应头中获取cookie数据,并存盘) => 该客户端再次发送请求的时候(会自动在请求头中携带cookie数据,其中就包含了sessionId) => 服务端再次接收请求的时候(从请求头的cookie中获取sessionId,然后根据sessionId获取对应的session,也就是存储空间,从而获取其中保存的数据)
session的配置
npm i express-session
- 挂载在中间件上,没设置匹配路径,所有请求都会经过此中间件
- 可以直接通过 中间件请求参数绑定用户信息
req.session.user = user
// session配置
app.use(session({
// sessionId加密
secret: 'secret key',
// cookie默认名 connect.id
name: 'uid',
// 是否保存未初始化的session,如果设为false,
// 那么在session中没有保存数据时,每次请求都会创建一个新的session对象,对于内存性能来说不友好
// 用默认值true,就好些,因为只有在第一次请求时候会创建,后面都是用的同一个对象
saveUninitialized: true,
// 刷新cookie过期时间
rolling: true,
// 设置cookie过期时间
cookie: {
maxAge: 30 * 60 * 1000
}
}))
密码加密bcrypt
npm i bcrypt
哈希加密是单程加密方式: 1234=>abcd
在加密的密码中加入随机字符串可以增加密码被破解的难度
// 导入bcrypt模块
const bcrypt = require('bcrypt')
// 生成随机字符串 gen => generate 生成 salt 盐
let salt = await bcrypt.genSalt(10)
// 使用随机字符串对密码进行加密
let pwd = await bcrypt.hash('明文密码',salt)
// 密码比对
let isEqual = await bcrypt.compare('明文密码', '加密密码');
文件上传
npm i formidable
form
中的 enctype
的作用是指定表单数据的编码类型 默认值是 application/x-www-form-urlencoded
如果涉及达到了表单中文件上传 则需要设置为 multipart/form-data
将表单数据编码成二进制类型
// 引入formidable第三方模块
const formidable = require('formidable');
const path = require('path');
const { Article } = require('../../model/article')
module.exports = (req, res) => {
// 1.创建表单解析对象
const form = new formidable.IncomingForm();
// 2.配置上传文件的存放位置
form.uploadDir = path.join(__dirname, '../', 'public', 'uploads');
// 3.保留上传文件的后缀
form.keepExtensions = true;
// 4.解析表单
form.parse(req, async (err, fields, files) => {
// 1.err错误对象 如果表单解析失败 err里面存储错误信息 如果表单解析成功 err将会是null
// 2.fields 对象类型 保存普通表单数据
// 3.files 对象类型 保存了和上传文件相关的数据
res.send(files.cover.path.split('public')[1])
})
// res.send('ok');
}
FileReader
使用FileReader 读取本地文件
const reader = new FileReader();
reader.readAsDataURL('文件');
reader.onload = function () {
console.log(reader.result);
}
Morgan
npm install morgan
// 获取系统环境变量 返回值是对象
if (process.env.NODE_ENV == 'development') {
// 当前是开发环境
console.log('当前是开发环境')
// 在开发环境中 将客户端发送到服务器端的请求信息打印到控制台中
app.use(morgan('dev'))
} else {
// 当前是生产环境
console.log('当前是生产环境')
}
Cross-env
npm i cross-env
可以在 package.json
中用来切换运行环境
"scripts": {
"prod": "cross-env NODE_ENV=prod nodemon app.js",
"dev": "cross-env NODE_ENV=dev nodemon app.js"
}