node
HTML中的外链:
- 我们都知道,浏览器如果解析到外链文件,会自动发送请求,如果你的外链地址写的是相对路径,那么相对的是浏览器地址栏中的请求路径,而非当前文件,浏览器会把地址栏中的请求路径的最后一段视为文件名,也就是说,在最后一段之前的路径才是相对路径外链的起始路径
- 既然这么复杂,我们总结一点即可规避这个问题:HTML中所有的外链,无脑写绝对路径,绝对路径就以以
/
开头即可
HTTP协议的特点:
- 无状态:是指协议对于事物处理没有记忆功能,也就是说,对于服务端来讲,他不关心客户端是谁,他只关心请求,请求来了服务端就响应,响应完了谁也不认识谁,这种特性严重阻碍了需要客户端与服务端进行动态交互的web应用程序的实现,所以呢,cookie和session这种用户保持HTTP连接状态的技术就应运而生了,就是为了解决这个缺陷的。
- cookie:通过客户端来保持状态的解决方案(供服务端存储数据)
- 以域名的形式进行区分
- 具体时效性,过期之后会被浏览器自动删除,如果你不设置过期时间,那么默认情况下会在关闭浏览器时删除
- 特别要注意:在发送请求的时候会自动携带到请求头中一并发送给服务端
- 交互流程:客户端请求服务端(携带请求数据) ==> 服务端响应客户端(在响应头中携带需要被客户端保存的cookie数据) ==> 客户端接收服务端响应(保存cookie数据,存盘,磁盘中) ==> 客户端再次发送请求的时候(自动在请求头中携带已有的cookie数据) ==> 服务端接收客户端请求(从请求头中获取cookie数据),后面的流程同上。。。
- session:通过服务端来保持状态的解决方案(供客户端存储数据)
- 是服务端为客户端开辟的存储空间,在其中保存数据
- 也有时效性,服务端重启时会失效
- 很重的一点,他是基于cookie来实现的,会将生成的sessionId以cookie的形式保存在客户端中
- 交互流程:客户端请求服务端(携带请求数据) ==> 服务端接收请求(给你开辟一个存储空间,用来保存你的数据,实际上就是创建session,并为之生成一个唯一的id,也就是sessionId) ==> 服务端响应客户端(在响应头中携带包含sessionId的cookie数据) ==> 客户端接收响应(从响应头中获取cookie数据,并存盘) ==> 该客户端再次发送请求的时候(会自动在请求头中携带cookie数据,其中就包含了sessionId) ==> 服务端再次接收请求的时候(从请求头的cookie中获取sessionId,然后根据sessionId获取对应的session,也就是存储空间,从而获取其中保存的数据)
分页核心要素:
- 当前页码:
page
,通过客户端传递参数获取- 不能小于1,如果小于1,则设置为1
- 不能大于
pages
,如果大于,则设置为pages
- 每页数据条数:
size
,根据业务需求,可以通过客户端传参获取,也可以规定死- 不能小于1,如果小于,则设置为默认值,默认值一般为10
- 总页数:
pages
,通过Math.ceil(total / size)
计算获取- 不能小于1,如果小于1,则设置为1
- 总数据条数:
total
,通过数据库查询获取,比如:User.countDocuments({ 查询条件 })
- 跳过多少条数据:通过
(page - 1) * size
计算得到,通过skip((page - 1) * size)
方法指定 - 拿多少条数据:就是
size
,通过limit(size)
方法指定
注意:以后遇到添加和修改操作,都分开搞,这样业务逻辑会清晰很多,也方便后期维护
form表单的enctype属性值说明:
- 默认值:application/x-www-from-urlencoded,将表单数据转换成形如get请求的参数:
name=zs&age=18
- 如果涉及到文件上传:multipart/form-data,将表单数据编码成二进制类型
第三方模块formidable:
-
作用:解析表单数据,支持get请求参数,post请求参数,文件上传
-
当有文件上传时,body-parser无法解析二进制数据,所以就需要借助这个模块了
-
核心代码:
const { IncomingForm } = require('formidable') // 创建表单解析对象 const form = new IncomingForm() // 设置文件上传目录,用绝对路径 form.uploadDir = '/path/to/you/upload/dir' // 是否保留文件的扩展名 form.keepExtensions = true; // 默认false,不保留 // 对表单进行解析 form.parse(req/* 请求对象 */, (err, fields, files) => { // err 错误对象 // fields 普通的请求参数,对象类型 // files 上传的文件信息,对象类型 })
图片预览:
// 获取文件input标签
const fileInput = document.querySelector('#fileInput')
// 获取预览img标签
const previewImg = document.querySelector('#previewImg')
// 监听onchange事件,当用户选择文件后触发
fileInput.onchange = function () {
// 创建文件读取对象
const fileReader = new FileReader()
// 读取文件,将文件转换成base64编码格式的url,这是一个异步函数,不能通过返回值的形式获取到结果
fileReader.readAsDataURL(this.files[0])
// 监听onload事件,当文件读取完后触发
fileReader.onload = () => {
// 将文件编码字符串设置到预览img元素的src属性上去
previewImg.src = fileReader.result
}
}
npm发布自己的模块常用命令
注意:必须切换到npm官方镜像上
- nrm ls
- nrm use npm
查看当前登录的用户
- npm whoami
登录
- npm login
发布
- npm publish --access=public
注意:当版本升级的时候,版本号不能和之前一样,需要增加
整体正常流程步骤
- 注册npm账号,验证邮箱(只有验证邮箱通过后才可以发布模块)
- 使用npm login命令登录自己的账号(注意切换到npm官方镜像上)
- 使用npm publish --access=public命令发布模块
注意:这些命令都需要在项目根目录下执行
开发映射测试
- 在模块项目中执行:npm link,这个意思是把当前项目先映射到本地的全局
- 在应用项目中执行:npm link 模块名,这个意思是把映射到全局的模块引入到项目中
引用自己写的npm模块去实现图片上传
// 先下载这个模块
npm i @andremao/form-parser
// 引入模块
const formParser = require('@andremao/form-parser')
// 创建中间件 使用图片商品模块
app.use(
formParser.parse({
// 设置图片上传的路径
// process.cwd() 获取项目根路径
uploadDir: path.join(process.cwd(), 'public/upload'),
// 保留文件的扩展名
keepExtensions: true,
})
)