admin管理员组文章数量:1656148
文章目录
- 1 Ajax
- 1.1 基础
- 1.1.1 客户端,服务器
- 1.1.1.1 通信过程
- 1.1.1.2 请求方式
- 1.1.2 URL地址
- 1.1.2.1 概念
- 1.1.2.2 URL地址组成
- 1.1.3 接口
- 1.1.3.1 接口概念
- 1.1.3.2 测试工具
- 1.2 Ajax
- 1.2.1 jQuery中的Ajax
- 1.2.1.1 $.get()语法
- 1.2.1.2 $.post()语法
- 1.2.1.3 $.ajax()语法
- 1.2.2 form表单
- 1.2.2.1什么是表单
- 1.2.2.2 form属性
- 1.2.2.3 监听表单提交事件
- 1.2.2.4 阻止表单默认提交行为
- 1.2.2.5 快速获取表单数据
- 1.2.3 模板引擎
- 1.2.3.1 基本概念
- 1.2.3.2 art-template简介
- 1.2.3.3 标准语法
- 1.2.3.4 正则与字符串操作
- 1.2.3.4.1 exec()检索
- 1.2.3.4.2 分组
- 1.2.3.4.3 replace()
- 1.2.3.5 实现自定义模板
- 1.2.4 XHR
- 1.2.4.1 基本使用
- 1.2.4.1.1 发送GET请求
- 1.2.4.1.2 发送POST请求
- 1.2.4.1.3 查询字符串
- 1.2.4.1.4 readstate属性
- 1.2.4.1.5 URL编码
- 1.2.4.2 数据交换格式
- 1.2.4.2.1 定义
- 1.2.4.2.2 XML
- 1.2.4.2.3 JSON
- 1.2.4.3 封装Ajax
- 1.2.4.4 Level 2新特性
- 1.2.4.4.1 旧版XHR缺点
- 1.2.4.4.2 XHRL2新功能
- 1.2.4.4.3 设置HTTP请求时限
- 1.2.4.4.4 FormData对象
- 1.2.4.4.5 上传文件
- 1.2.4.4.6 上传文件进度
- 1.2.4.5 jQuery高级用法
- 1.2.4.6 axios
- 1.2.5 同源和跨域
- 1.2.5.1 同源
- 1.2.5.2 跨域
- 1.2.5.3 JSONP
- 1.2.5.4 防抖
- 1.2.5.5 节流
- 1.2.6 HTTP
- 1.2.6.1 协议简介
- 1.2.6.2 HTTP请求消息
- 1.2.6.2.1 请求行
- 1.2.6.2.2 请求头部
- 1.2.6.2.3 空行
- 1.2.6.2.4 请求体
- 1.2.6.3 HTTP响应消息
- 1.2.6.3.1 状态行
- 1.2.6.3.2 响应头部
- 1.2.6.3.3 空行
- 1.2.6.3.4 响应体
- 1.2.6.4 HTTP请求方法
- 1.2.6.5 HTTP响应状态码
- 1.2.6.5.1 成功相关2
- 1.2.6.5.2 重定向相关3
- 1.2.6.5.3 客户端相关4
- 1.2.6.5.4 服务端相关5
- 2 Git
- 2.1 简介
- 2.1.1 版本控制
- 2.1.2 版本控制系统分类
- 2.1.2.1 本地版本控制系统
- 2.1.2.2 集中化版本控制系统
- 2.1.2.3 分布式版本控制系统
- 2.1.3 Git介绍
- 2.1.3.1 什么是Git
- 2.1.3.2 Git特性
- 2.1.3.3 SVN差异比较
- 2.1.3.4 Git记录快照
- 2.1.3.5 Git三个区域
- 2.1.3.6 Git三种状态
- 2.1.3.7 Git工作流程
- 2.1.4 安装配置Git
- 2.1.4.1 安装
- 2.1.4.2 配置
- 2.2 Git基础
- 2.2.1 安装配置命令
- 2.2.2 Git仓库
- 2.2.3 Git基础操作
- 2.2.4 文件状态
- 2.2.5 工作步骤
- 2.2.6 git log自定义格式
- 2.2.7 忽略文件
- 2.3 GitHub
- 2.3.1 开源
- 2.3.1.1 开源
- 2.3.1.2 闭源
- 2.3.1.3 开源许可协议
- 2.3.1.4 为什么要开源
- 2.3.1.5 开源托管平台
- 2.3.2 什么是GitHub
- 2.3.3 注册GitHub
- 2.3.4 新建空白远程仓库
- 2.3.5 访问远程仓库
- 2.3.5.1 HTTP访问
- 2.3.5.2 SSH访问
- 2.3.5.2.1 SSH key
- 2.3.5.2.2 生成SSH key
- 2.3.5.2.3 配置SSH key
- 2.3.5.2.4 检测配置成功
- 2.3.5.2.5 本地仓库上传GitHub
- 2.3.5.3 从远程仓库克隆到本地
- 2.4 Git分支
- 2.4.1 分支概念
- 2.4.2 本地分支操作
- 2.4.3 远程分支操作
- 3 Node.js
- 3.1 初识Node
- 3.1.1 Node.js与浏览器的区别
- 3.1.2 Node.js作用
- 3.1.3 Node.js使用
- 3.2 Node.js模块化开发
- 3.2.1 基本概念
- 3.2.1.1 什么是模块化
- 3.2.1.2 模块化规范
- 3.2.1.3 Node模块分类
- 3.2.1.4 加载模块
- 3.2.1.5 模块作用域
- 3.2.1.6 向外共享模块作用域中的成员
- 3.2.1.7 Node.js的模块化规范
- 3.3 fs文件系统模块
- 3.3.1 什么是fs模块
- 3.3.2 读取文件
- 3.3.3 写入文件
- 3.3.4 回调函数参数值
- 3.3.5 路径拼接问题
- 3.4 path路径模块
- 3.4.1 什么是path模块
- 3.4.2 路径拼接
- 3.4.3 获取文件名
- 3.4.4 获取文件扩展名
- 3.5 http模块
- 3.5.1 什么是http模块
- 3.5.2 http模块作用
- 3.5.3 IP地址
- 3.5.4 服务器概念
- 3.5.4.1 域名
- 3.5.4.2 端口号
- 3.5.4.3 创建最基本的Web服务器
- 3.5.4.3.1 步骤
- 3.5.4.3.2 req请求对象
- 3.5.4.3.3 res请求对象
- 3.5.4.3.4 根据不同url响应不同html
- 3.6 npm与包
- 3.6.1 包
- 3.6.2 npm包管理工具
- 3.6.2.1 npm命令
- 3.6.2.2 初次装包
- 3.6.2.3 包的语义化版本规范
- 3.6.2.4 包管理配置文件
- 3.6.2.5 解决下载慢问题
- 3.6.2.6 nrm
- 3.6.2.7 格式化时间
- 3.6.2.8 md转html
- 3.6.3 包的分类
- 3.6.3.1 项目包
- 3.6.3.2 全局包
- 3.6.4 包结构
- 3.7 模块加载机制
- 3.7.1 优先从缓存加载
- 3.7.2 内置模块加载机制
- 3.7.3 自定义模块加载机制
- 3.7.4 第三方模块加载机制
- 3.7.5 目录作为模块
- 4 Express
- 4.1 Express基础
- 4.1.1 Express简介
- 4.1.2 基本使用
- 4.1.2.1 监听GET请求
- 4.1.2.2 监听POST请求
- 4.1.2.3 响应内容给客户端
- 4.1.2.4 获取URL中携带的查询参数
- 4.1.2.5 获取URL动态参数
- 4.1.2.6 托管静态资源
- 4.1.2.7 创建基本Web服务器
- 4.1.2.8 nodemon
- 4.2 Express路由
- 4.2.1 路由的概念
- 4.2.2 路由的使用
- 4.2.3 创建路由模块
- 4.2.4 注册路由模块
- 4.3 Express中间件
- 4.3.1 中间件概念
- 4.3.1.1 中间件的定义
- 4.3.1.2 中间件的调用流程
- 4.3.1.3 中间件的格式
- 4.3.1.4 next函数作用
- 4.3.1.5 中间件作用
- 4.3.2 定义中间件
- 4.3.2.1 定义中间件函数
- 4.3.2.2 定义全局生效中间件
- 4.3.2.3 简写定义全局中间件
- 4.3.2.4 定义多个全局中间件
- 4.3.2.5 定义局部生效中间件
- 4.3.2.6 定义多个局部中间件
- 4.3.3 中间件注意事项
- 4.3.4 中间件分类
- 4.3.4.1 应用级别中间件
- 4.3.4.2 路由级别中间件
- 4.3.4.3 错误级别中间件
- 4.3.4.4 内置中间件
- 4.3.4.5 第三方中间件
- 4.4 Express写接口
- 4.4.1 CORS跨域资源共享
- 4.4.1.1 什么是cors
- 4.4.1.2 使用CORS中间件
- 4.4.1.3 注意事项
- 4.4.1.4 CORS响应头部ACAO
- 4.4.1.5 CORS响应头部ACAH
- 4.4.1.6 CORS响应头部ACAM
- 4.4.1.7 简单请求
- 4.4.1.8 预检请求
- 4.4.1.9 请求区别
- 4.4.2 JSONP接口
- 4.4.2.1 回顾JSONP
- 4.4.2.2 实现JSONP接口步骤
- 4.4.2.3 网页中使用JQuery发起JSONP请求
- 4.4.2.4 注意事项
- 4.5 Express操作数据库
- 4.5.1 步骤
- 4.5.2 安装mysql模块
- 4.5.3 配置mysql模块(连接数据库)
- 4.5.4 操作语句
- 4.5.4.1 查询数据
- 4.5.4.2 插入数据
- 4.5.4.3 插入简写
- 4.5.4.4 更新数据
- 4.5.4.5 更新简写
- 4.5.4.6 删除数据
- 4.5.4.7 标记删除
- 4.6 前后端身份认证
- 4.6.1 Web开发模式
- 4.6.1.1 服务器渲染的Web开发模式
- 4.6.1.2 前后端分离的Web开发模式
- 4.6.1.3 如何选择开发模式
- 4.6.2 身份认证概念
- 4.6.2.1 什么是身份认证
- 4.6.2.2 身份认证目的
- 4.6.2.3 认证机制
- 4.6.3 Session认证机制
- 4.6.3.1 Session原理
- 4.6.3.2 Cookie概念
- 4.6.3.3 Cookie特性
- 4.6.3.4 Cookie作用
- 4.6.3.5 Cookie不具有安全性
- 4.6.3.6 Session工作原理
- 4.6.3.7 Express中使用Session
- 4.6.3.8 Session的局限性
- 4.6.4 JWT认证机制
- 4.6.4.1 JWT概念
- 4.6.4.2 JWT工作原理
- 4.6.4.3 JWT组成部分
- 4.6.4.4 JWT使用方式
- 4.6.4.5 Express中使用JWT
- 4.6.4.5 Express中使用JWT
1 Ajax
1.1 基础
1.1.1 客户端,服务器
- 客户端 : 获取和消费资源的电脑
- 服务器 : 存放和对外提供资源的电脑
1.1.1.1 通信过程
- 请求-处理-响应三步骤
1.1.1.2 请求方式
- 需要用到XMLHttpRequest对象
- get请求 : 获取资源
- 获取文件,图片,样式,数据等
- post请求 : 提交数据
- 提交登录信息,注册信息,用户信息等
1.1.2 URL地址
1.1.2.1 概念
- 中文名称 : 统一资源定位符(相当于人的身份证)
- 用于标识互联网上每个资源的唯一存放位置
1.1.2.2 URL地址组成
- 客户端与服务器的通信协议(http(s))
- 存有该资源的服务器名称(www.xxx)
- 资源在服务器上的位置(/ahuickcbna/hazoicbd.html)
1.1.3 接口
1.1.3.1 接口概念
- Ajax请求数据时,被请求的URL地址,叫做接口
- 每个接口必须有请求方式
1.1.3.2 测试工具
- 不写任何代码的情况下对进口进行调用和测试
- 测试GET请求 :
- 选择请求方式
- 填写URL
- 选择Header
- 填写参数
- 点击发送
- 查看结果
- 测试POST请求 :
- 选择请求方式
- 填写URL
- 选择Body
- 选择数据格式
- 填写数据
- 点击发送
- 查看结果
1.2 Ajax
- 全称 : Asynchronous Javascript And XML(异步 JavaScript和XML)
- 网页中利用XMLHttpRequest对象和服务器进行数据交互的方式
1.2.1 jQuery中的Ajax
- 浏览器中的XMLHttpRequest用法比较复杂,jQuery对其进行了封装
- 提供了一系列Ajax相关的函数,极大地降低了Ajax的使用难度
- jQuery中发起Ajax的三个方式 :
- $.get()
- $.post()
- $.ajax()
1.2.1.1 $.get()语法
- 专门用来发起get请求
- 语法 :
$.get(url,[data],[callback])
- 参数 :
参数名 | 类型 | 是否必选 | 说明 |
---|---|---|---|
url | string | 是 | 请求的地址 |
data | object | 否 | 指定要请求的元素参数(eg : id=1) |
callback | function | 否 | 请求成功的回调函数 |
1.2.1.2 $.post()语法
- 专门用来发起post提交
- 语法 :
$.post(url,[data],[callback])
参数名 | 类型 | 是否必选 | 说明 |
---|---|---|---|
url | string | 是 | 提交的地址 |
data | object | 否 | 指定要提交的数据 |
callback | function | 否 | 提交成功的回调函数 |
1.2.1.3 $.ajax()语法
- 可以进行get和post请求
- 参数为一个具有四个属性对象 :
- type/method : 请求类型,‘GET’/‘POST’
- url : 请求地址
- data : 携带的数据
- success : 成功后的回调函数
1.2.2 form表单
1.2.2.1什么是表单
- 主要负责数据采集功能
- HTML中的form标签
- 缺点 :
- 页面会跳转
- 页面跳转之前的状态和数据会丢失
- 解决办法 : 表单只负责采集,Ajax负责提交
1.2.2.2 form属性
属性 | 值 | 描述 |
---|---|---|
action | URL地址 | 向何处发送表单数据 |
method | get/post | 用什么方式提交 |
enctype | application/x-www-form-urlencoded multipart/form-data text/plain | 发送表单之前如何编码 |
target | blank/self/parent/top | 发送结束后在何处打开发送后的页面 |
- 涉及文件上传,必须将enctype设置成multipart/form-data
- 无文件则设置成application/x-www-form-urlencoded
1.2.2.3 监听表单提交事件
- jQuery中有两种监听表单提交事件
$('#form1').submit(function(e){
...
})
$('#form2').on('submit',function(e){
})
1.2.2.4 阻止表单默认提交行为
- 监听到表单提交事件后,可以调用事件对象的**event.preventDefault()**函数阻止提交和跳转
$('#form1').submit(function(e){
e.preventDefault()
})
$('#form1').on('submit',function(e){
e.preventDefault()
})
1.2.2.5 快速获取表单数据
- serialize()函数
- 必须为每一个表单元素头添加name属性
<form id="form1">
<input type="text" name="username"/>
<input type="password" name="password"/>
<button type="submit">
提交
</button>
</form>
$('#form1').serialize();
1.2.3 模板引擎
1.2.3.1 基本概念
- 根据程序员指定的模板结构和数据,自动生成HTML页面
- 好处 :
- 减少了字符串拼接操作
- 使代码更清晰
- 使代码易于阅读和维护
1.2.3.2 art-template简介
- 简介 :
- 简约超快的模板引擎
- 中文官网 : http://aui.github.io/art-template/zh-cn/index.html
- 安装 :
- 访问官网,找到下载链接
- 另存为本地,通过script标签加载到网上
- 使用 :
- 导入art-template
- 定义数据
- 定义模板
- 调用template函数
- 渲染HTML页面
1.2.3.3 标准语法
-
**{{}}**内进行变量输出,循环数组等
-
输出
- 变量 : {{value}}
- 对象属性 : {{obj.value}}
- 三元表达式 : {{a ? b : c}}
- 逻辑输出 : {{a || b}}
- 加减乘除 : {{a + b}}
- 原文输出 : 在原文前加上@符号 {{@ value}}
- 条件输出 :
- {{if value}} 输出内容 {{/if}}
- {{if value1}} 输出内容1 {{else if value2}} 输出内容2 {{/if}}
- 循环输出 :
{{each arr}} {{$index}} {{$value}} {{/each}}
- 过滤器 :
- 本质是一个function处理函数,类似于自己封装函数
- 定义 :
- template.defaults.imports.函数名 = function(value){return 操作结果}
- 语法 : {{value | 函数名}}
1.2.3.4 正则与字符串操作
1.2.3.4.1 exec()检索
- 检索字符串中的真正则表达式的匹配
- 字符串中有匹配的值,返回该值,无则返回null
- 语法 : 正则表达式.exec(字符串)
- 返回一个数组,包含
- 正则表达式匹配到的内容,
- ()提取的内容,
- 在字符串的位置
- 位于哪个字符串
- groups
1.2.3.4.2 分组
-
()包起来的内容为一组
-
通过分组来提取自己想要的内容
-
var str = '<div>我是{{name}}</div>' var pattern = /{{([a-zA-Z]+)}}/ console.log(pattern.exec(str)) // ["{{name}}", "name", index: 7, input: "<div>我是{{name}}</div>", groups: undefined]
1.2.3.4.3 replace()
- 用于在字符串中,用一些字符替代另一些字符
- 通过用exec()的1元素替换0元素来去除{{}}
- 原文输出时,重复多次使用replace使每一个{{}}都不被输出
- 可以使用while循环来多次replace,条件是exec()
- 替换真值 :
- 把exec()返回数组的1元素传入到对象中,作为属性
- 来查找该属性对应的值
- str.replace(str1[0],data[str1[1]])
1.2.3.5 实现自定义模板
<script type="text/html" id="tpl-user">
<div>姓名:{{name}}</div>
<div>年龄:{{ age }}</div>
<div>性别:{{ gender}}</div>
<div>住址:{{address }}</div>
</script>
<script>
let data = {
name: 'zs',
age: 28,
gender: '男',
address: '北京顺义马坡'
}
let htmlStr = template('tpl-user', data)
document.getElementById('user-box').innerHTML = htmlStr
</script>
function template(id,data) {
let str = document.getElementById(id).innerHTML
let pattern = /{{\s*([a-zA-Z]+)\s*}}/
let pattResult = null
while (pattResult = pattern.exec(str)) {
str = str.replace(pattResult[0],data[pattResult[1]])
}
return str
}
1.2.4 XHR
1.2.4.1 基本使用
- XMLHttpRequest简称xhr
- xhr是浏览器提供的JavaScript对象,通过它可以请求服务器上的数据资源
- Ajax函数是基于xhr封装而来的
1.2.4.1.1 发送GET请求
- 创建xhr对象
- 调用xhr.open()函数
- 调用xhr.send()函数
- 监听xhr.onreadystatechange事件
- 请求带参数的GET
- 在open函数中的URL地址末尾添加查询字符串
- 发送GET请求本质 :
1.2.4.1.2 发送POST请求
- 创建xhr对象
- 调用xhr.open()函数
- 设置Content-Type属性(固定写法)
- 调用xhr.send()函数,同时提交数据
- 监听xhr.onreadystatechange事件
1.2.4.1.3 查询字符串
- 定义 : 在URL末尾加上的用于向服务器发送信息的字符串
- 格式 :
- **?**放在URL末尾,分开URL地址和信息
- 每个信息用属性=值的格式书写
- 多个参数之间用**&**分开
1.2.4.1.4 readstate属性
1.2.4.1.5 URL编码
- 编码 :
- URL地址中只允许出现英文相关字母,标点符号,数字,不允许出现中文
- 需要包含中文时则必须对中文编码
- 编码原则 : 使用安全的字符表示不安全字符(使用英文表示非英文)
- 浏览器会自动编码,大多情况下不需要关心
- 通常情况下**三组(%+两位数)**表示一个汉字(eg : %E9%BB%AC)
- 如何编码解码 :
- 编码
1.2.4.2 数据交换格式
1.2.4.2.1 定义
- 服务器与客户端之间进行的数据传输与交换格式
- 前端经常提到的格式分别是XML和JSON
1.2.4.2.2 XML
- 全称 : EXtensible Markup Language (可扩展标记语言)
- 和HTML类似
- 区别 :
- HTML描述网页内容,是网页内容的载体
- XML用于传输和存储数据,是数据的载体
- XML缺点 :
- 格式臃肿,和数据无关的代码太多(标签名),体积大但是传输效率低
- JS解析XML比较麻烦
1.2.4.2.3 JSON
- 定义 : JavaScript Object Notation (JavaScript对象表示法)
- 本质 : 字符串
- 作用 : 轻量级的文本传输格式
- 优点 : 更小更快更易解析
- 两种结构 : 对象,数组(可以互相嵌套)
- 对象 :
- **{}**中的内容
- 内部用键值对表示
- 键值对中间用冒号分开
- 键值对之间用英文逗号隔开
- 属性值必须用双引号包裹,属性值包不包都可,最好包裹
- 数据类型 : 数字,字符串,布尔值,null,数组,对象六种
- 数组 :
- **[]**中的内容
- 值之间用英文逗号隔开
- 字符串用双引号包裹
- 数据结构 : 数字,字符串,布尔值,null,数组,对象六种
- 对象 :
- 注意事项 :
- 不能写注释
- 字符串用双引号包裹
- 无undefined
- JSON与JS对象关系
- JSON是JS对象的字符串表示法,本质是字符串
- JSON与JS对象转换
- JSON转为JS对象 :
- 使用**JSON.parse(‘对象’);**函数,
- 输出这个对象
- JS对象转换成JSON :
- 使用**JSON.stringify(对象);**函数
- 输出**‘对象’**
- JSON转为JS对象 :
- 序列化 : 数据对象转化成字符串
- 反序列化 : 字符串转化成数据对象
1.2.4.3 封装Ajax
- myajax()(ithema())函数是我们自己的Ajax函数
- 接受一个配置对象作为参数
- 配置对象属性 :
- method : 请求类型
- url : 请求地址
- data : 携带的数据
- success() : 回调函数
- 处理data函数
- 定义myajax()函数
- 判断请求类型
1.2.4.4 Level 2新特性
1.2.4.4.1 旧版XHR缺点
- 只支持文本数据传输,无法读取,上传文件
- 传送和接收数据时,无进度信息
1.2.4.4.2 XHRL2新功能
- 可以设置HTTP请求时限
- 可以使用FormData对象管理表单数据
- 可以上传文件
- 可以获得进度条
1.2.4.4.3 设置HTTP请求时限
-
语法 :
- 设置等待时长 : timeout属性(时长自定义)
xhr.timeout = 3000
- 回调函数 : ontimeout
xhr.ontimeout = function(event){ . }
1.2.4.4.4 FormData对象
- HTML5新增的对象
- 模拟表单操作
- 获取网页表单的值
1.2.4.4.5 上传文件
- 定义UI结构
- 验证是否选择了文件
- 向FormData中追加文件
-
使用xhr发起上传文件请求
-
监听 onreadystatechange事件
1.2.4.4.6 上传文件进度
- 新版XHR对象中,可以通过监听xhr.upload.onprogress事件来获取上传进度
- 语法 :
- 监听上传进度的事件
- 监听上传完成的事件
1.2.4.5 jQuery高级用法
- 定义UI结构
- 验证是否选择了文件
- 向FormData中追加文件
- jQuery发起请求
- 实现loading进度条效果
1.2.4.6 axios
- 定义 :
- 专注于网络数据请求的库
- 简单易用
- 轻量化
- 发起GET请求 :
- 发起POST请求 :
-
axios()发起请求 :
- 语法 :
axios({ method: '请求类型', url: '请求地址', data: {/*POST数据*/}, params: {/*GET数据*/} }).then(callback)
- GET请求 :
- POST请求 :
1.2.5 同源和跨域
1.2.5.1 同源
- 两个页面协议,域名,端口都相同,则这两个页面具有相同的源
- 同源策略 :
- 浏览器的一个安全功能
- 无法读取非同源网页的Cookie,LocalStorage,IndexedDB
- 无法接触非同源网页的DOM
- 无法向非同源地址发送Ajax请求
- 原理 : 浏览器对跨域请求的拦截,服务器可以接收请求,但是客户端接收的数据会被拦截
1.2.5.2 跨域
- 非同源就是跨域
- 如何实现 : JSONP和CORS
1.2.5.3 JSONP
- 原理 : script标签可以请求非同源的脚本
- 通过script的src请求跨域接口,通过函数调用的形式接收数据
- 自己实现简单的JSONP
- script内定义回调函数success(data)
- script的src输入请求接口和请求数据
- 缺点 :
- 只能GET
- jQuery中的JSONP
- 使用 : $.ajax()函数设置dataType为jsonp : dataType: ‘jsonp’
- 自定义回调函数名称 : jsonp: ‘回调名称’
- 自定义参数名称 : jsonpCallback: ‘名称’
- 实现过程 :
- 发起JSONP时,动态向header标签里添加一个script标签
- JSONP请求成功后删除标签
1.2.5.4 防抖
-
定义 : 事件被触发后延迟n秒再执行,n秒内再次触发则重新计时
-
应用场景 : 输入框连续输入字符,等输入完毕后才请求
-
实现 :
- 输入框防抖 :
- 定义全局缓存对象
var cacheOnj = {}
- 把搜素结果保存到缓存对象中
- 优先从缓存中搜索建议
1.2.5.5 节流
-
定义 : 单位时间内事件只触发一次
-
节流阀 :
- 节流阀为空,可以执行下次操作
- 节流阀非空,不可执行下次操作
- 当前操作开始,将节流阀非空
- 当前操作完毕,将节流阀置空
- 每次执行之前先判断是否为空
1.2.6 HTTP
1.2.6.1 协议简介
- 通信 :
- 信息的传递和交流
- 三要素 : 主体,内容,方式
- 通信协议 :
- 通信双方完成通信必须遵守的规则和约定
- HTTP协议 :
- 超文本传输协议(Hyper Text Transfer Protocol)
- 采用请求/响应的交互模型
1.2.6.2 HTTP请求消息
- HTTP请求 : 客户端发起的请求
- HTTP请求消息 : 客户端发送到服务器的消息,也叫HTTP请求报文
- 组成部分 :
- 请求行 (request line)
- 请求头部(header)
- 空行
- 请求体
- 每个行末都会有一个回车符和一个换行符,空行无
1.2.6.2.1 请求行
- 由请求方式,URL,HTTP协议版本三部分组成
- 他们之间用空格分隔
1.2.6.2.2 请求头部
- 描述用户基本信息
- 把客户端相关的信息告知服务器
- 用多行键值对组成,每行的键和值用冒号分隔
- 常见请求字段 :
头部字段 | 说明 |
---|---|
Host | 请求的服务器域名 |
Connection | 客户端服务器连接方式(close/keepalive) |
Content-Length | 请求体大小 |
Accept | 客户端可识别的内容类型列表 |
User-Agent | 产生请求的浏览器类型 |
Content-Type | 实际发送的数据类型 |
Accept-Encoding | 可接收的内容压缩编码形式 |
Accept-Language | 用户希望获得的自然语言优先顺序 |
1.2.6.2.3 空行
- 通知请求头部到此结束
- 用来分隔请求头部和请求体
1.2.6.2.4 请求体
- 存放POST方式提交到服务器的数据
- 只有POST请求才有请求体
1.2.6.3 HTTP响应消息
- 服务器响应给客户端的消息内容
- 也叫响应报文
- 组成部分 :
- 状态行
- 响应头部
- 空行
- 响应体
- 每个行末都会有一个回车符和一个换行符,空行无
1.2.6.3.1 状态行
- 由HTTP协议版本,状态码,状态码描述文本三部分组成
- 之间用空格隔开
1.2.6.3.2 响应头部
- 描述服务器基本信息
- 由键值对组成
- 键值对中间用冒号分隔
1.2.6.3.3 空行
- 响应头部到此结束
- 用来分隔响应头部和响应体
1.2.6.3.4 响应体
- 存放服务器响应给客户端的资源内容
1.2.6.4 HTTP请求方法
- 定义 : 表明要对服务器上的资源执行的操作
- 常见的是GET和POST
- HTTP请求方法
方法 | 描述 |
---|---|
GET | (查询)发送请求获取服务器上的资源,请求体中无数据,请求数据放在协议头中 |
POST | (新增)向服务器提交资源,数据被包含在请求体中提交给服务器 |
PUT | (修改)向服务器提交资源,并使用提交的新资源,替换服务器上对应的的旧资源 |
DELETE | (删除)请求服务器删除指定资源 |
HEAD | 与GET相同作用,但是无响应体 |
OPYIONS | 获取http服务器支持的http请求方法,允许客户端查看服务器的性能 |
CONNECT | 建立一个到由目标资源表示的服务器的隧道 |
TRACE | 沿着到目标资源的路径执行一个消息环回测试 |
PATCH | PUT的补充,用来对已知资源进行局部更新 |
1.2.6.5 HTTP响应状态码
- 用来标识响应的状态
- 会随着响应消息一起被发送到客户端浏览器
- 浏览器根据服务器返回的响应状态码,就知道这次请求是否成功
- 组成 : 由三个十进制数字组成 :
- 第一个数字定义了状态码类型
- 后两个用来对状态码进行细分
- 五类状态码 :
分类 | 描述 |
---|---|
1** | 信息,服务器收到请求,需要请求这继续执行操作(实际开发中很少见) |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步操作来完成请求 |
4** | 客户端错误,请求包含语法错误或者无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
1.2.6.5.1 成功相关2
状态码 | 英文名称 | 描述 |
---|---|---|
200 | OK | 请求成功,一般用于GET和POST |
201 | Created | 已创建,成功请求并创建了新的资源,通常用于POST和OUT |
1.2.6.5.2 重定向相关3
状态码 | 英文名称 | 描述 |
---|---|---|
301 | Moved Permanly | 永久移动,请求的资源永久移动到新的URL,返回的信息包括新的URL,浏览器会自动定向到新的URL,今后任何新请求都使用新的URL代替 |
302 | Found | 临时移动,与301类似,但是资源只是临时被移动,客户端会继续使用原有URL |
304 | Not Modified | 未修改,所请求的资源未修改,服务器返回此状态码时,不会返回任何资源,客户端通常会缓存访问过的资源 |
1.2.6.5.3 客户端相关4
- 客户端请求有非法内容或者语法错误,导致请求失败
状态码 | 英文名称 | 描述 |
---|---|---|
400 | Bad Request | 1,语义有误当前请求无法被服务器理解 2,请求参数有误 |
401 | Unauthorized | 当前请求需要用户验证 |
403 | Forbidden | 服务器已经理解请求,但是拒绝执行 |
404 | Not Found | 服务器无法根据客户端的请求找到资源 |
408 | Request Timeout | 请求超时 |
1.2.6.5.4 服务端相关5
状态码 | 英文名称 | 描述 |
---|---|---|
500 | Internal Server Error | 服务器内部错误 |
501 | Not Implemented | 服务器不支持该请求方法 |
502 | Service Unavailable | 由于超载或者系统维护,服务器暂时无法处理 |
2 Git
2.1 简介
2.1.1 版本控制
- 手动控制 :
- 操作麻烦 : ,每次都要复制->粘贴->重命名
- 命名不规范 : 无法通过文件名知道具体做了什么修改
- 容易丢失 : 如果硬盘故障或者不小心删除,文件很容易丢失
- 协作困难 : 需要手动合并每个人对项目文件的修改,容易出错且麻烦
- 控制软件 :
- 用来记录文件变化,以便查阅特定版本修订情况的系统
- 把手动管理文件版本的方式,改为由软件管理文件版本
- 操作简便 : 只需记录简单的终端命令,即可快速上手
- 易于对比 : 基于功能,能够方便的比较文件的变化细节
- 易于回溯 : 可以将选定文件回溯到之前的状态
- 不易丢失 : 被误删的文件可以轻松恢复回来
- 协作方便 : 基于分支功能,可以轻松实现多人协作开发的代码合并
2.1.2 版本控制系统分类
2.1.2.1 本地版本控制系统
- 单机运行,使维护文件版本的操作工具化
- 使用软件记录文件不同版本
- 不支持多人开发
- 数据库故障后,所有历史记录会消丢失
2.1.2.2 集中化版本控制系统
- 联网运行,支持多人开发
- 基于服务器,客户端的运行模式
- 服务器保存文件的所有更新记录
- 客户端只保留最新文件版本
- 不支持离线提交版本更新
- 中心服务器崩溃后,所有人无法工作
- 数据库故障后,所有历史记录会消丢失
2.1.2.3 分布式版本控制系统
- 联网运行,支持多人开发
- 客户端断网后支持离线本地提交
- 服务器故障后,可以使用任何一个客户端的备份进行恢复
- 基于服务器,客户端的运行模式
- 客户端是服务器的完整备份,并不是只保留最新版本
2.1.3 Git介绍
2.1.3.1 什么是Git
- 开源的分布式版本控制系统
- 目前世界上最先进,最流行的版本控制系统
- 可以快速高效处理任意大小的项目版本管理
2.1.3.2 Git特性
- 直接记录快照,而非差异比较
- 近乎所有操作都是本地执行
- 断网后依旧可以在本地对项目进行版本管理
- 联网后,把本地修改的记录同步到云端服务器即可
2.1.3.3 SVN差异比较
- 传统版本控制系统(例如SVN)
- 基于差异的版本控制
- 存储的是一组基本文件和每个文件随时间逐步累积的差异
- 好处 : 节约磁盘
- 缺点 : 耗时,效率低
2.1.3.4 Git记录快照
- Git快照是在原有文件版本基础上重新生成一份新的文件,类似于备份
- 为了效率,如果文件没有修改,不再重新存储该文件,只保留一个链接指向之前的文件
- 缺点 : 占用磁盘空间大
- 优点 : 版本切换快
- 特点 : 空间换时间
2.1.3.5 Git三个区域
- 工作区 : 处理工作的区域
- 暂存区 : 已完成的工作的临时存放区域,等待被提交
- Git仓库 : 最终的存放区域
2.1.3.6 Git三种状态
- 已修改 : 修改了文件,但是还没提交到暂存区
- 已暂存 : 暂存了文件,但是没提交到仓库
- 已提交 : 文件已经安全的保存到本地Git仓库
- 注意 :
- 工作区的文件被修改了但是没放到暂存区,就是已修改
- 文件已修改并放入了暂存区,就是已暂存
- Git仓库里的文件是已提交的状态
2.1.3.7 Git工作流程
- 在工作区修改文件
- 暂存
- 提交更新,存储到GIT仓库
2.1.4 安装配置Git
2.1.4.1 安装
- 官网 : https://git-scm/downloads
2.1.4.2 配置
-
设置自己的用户名
-
git config --global user.name "名字"
-
设置自己邮箱
-
git config --global user.email "邮箱地址"
-
–global : 永久生效命令
-
生成的信息储存在C/User?用户名/.gitconfig(全局配置文件)中
-
检查配置信息
- 全部信息 : git config --list --global
- 指定信息 : git config user.name
2.2 Git基础
2.2.1 安装配置命令
代码 | 作用 |
---|---|
git config --global user.name “名字” | 设置自己的用户名 |
git config --global user.email “邮箱” | 设置自己邮箱 |
git config --list --global | 检查全部配置信息 |
git config user.name | 检查指定配置信息 |
git help config | 打开git config命令帮助手册 |
git config -h | 打开git config命令快速参考 |
2.2.2 Git仓库
- 获取Git仓库的两种方式 :
- 将尚未进行版本控制的本地目录转为Git仓库
- 从其他服务器克隆一个已存在的Git仓库
- 现有目录中初始化Git仓库
- 在项目目录中,鼠标右键打开Git Bash
- 执行git init 命令将当前的目录转化为Git仓库
- 该命令会创建一个名为**.git**的隐藏目录,这个目录就是当前项目的Git仓库
- 库里包含了初始必要文件,这些文件是Git仓库必要组成部分
- 工作区中文件四种状态
- 未跟踪 : 不被Git管理的文件
- 未修改 : 工作区中的文件和Git仓库中文件内容一致
- 已修改 : 工作区中的文件和Git仓库中文件内容不一致
- 已暂存 : 工作区中的文件已被放到暂存区
- Git操作最终结果 : 工作区中的文件都处于未修改状态
2.2.3 Git基础操作
代码 | 作用 | 简述 |
---|---|---|
git status | 查看文件状态 | 查看 |
git status -s/–short | 查看文件状态(以精简方式) | 查看 |
git log [-n] [–pretty=oneline] | 历史提交 [展示条数] [一行展示] | 查看 |
git log [-n] [–pretty=format:“”] | 历史提交 [展示条数] [自定义输出格式] | 查看 |
git add 文件名 | 跟踪新文件,修改文件到暂存区,解决冲突 | 更新 |
git add . | 将所有新增和修改的文件加入暂存区 | 更新 |
git commit -m “描述” | 提交更新到Git仓库,描述是提示性文案 | 提交 |
git commit -a -m “描述” | 跳过跟踪,直接提交到Git仓库 | 提交 |
git reset HEAD 文件名 | 从暂存区移除文件 | 移除 |
git rm -f 文件名 | 从Git仓库和工作区同时移除文件 | 移除 |
git rm --cached 文件名 | 只移除Git仓库中的文件 | 移除 |
git checkout – 文件名 | 撤销修改 | 恢复 |
git reset --hard <CommitID | 退到指定版本,ID后要**>** | 恢复 |
2.2.4 文件状态
状态 | git status下显示 | git status -s下显示 |
---|---|---|
未跟踪 | Untracked files中红色文件名 | 两个红色问号+文件名 |
已暂存 | Change to be committed中绿色文件名 | 一个绿色字母A+文件名 |
已提交 | 提示所有文件都处于未修改,无文件需要提交 | 同git status |
改且存 | Change not staged for commit中绿色文件名 | 一个红色字母M+文件名 |
改并存 | Change to be committed中绿色文件名 | 一个绿色字母M+文件名 |
2.2.5 工作步骤
- 跟踪提交文件,修改文件
- git add 文件名
- git status -s/–short
- git commit -m “描述”
- git status -s/–short
- 直接提交
- git commit -a -m “描述”
- git status -s/–short
2.2.6 git log自定义格式
- 语法 : git log [-n] [–pretty=format:“”]
- **“”**中的属性 :
- %h : 提交的简写哈希值
- %an : 作者名
- %ar : 作者修订日期(按多久前显示)
- %s : 提交说明
- 属性之间可以用符号分隔
2.2.7 忽略文件
- 有一些文件无需纳入Git的管理,也不希望他总出现在跟踪列表
- 方法 : 创建一个名为**.gitignore**的配置文件,列出要忽略的文件名
- 匹配模式 :
- #开头 : 注释
- /结尾 : 目录
- /开头 : 防止递归
- !开头 : 取反
- 可以使用glob模式进行文件和文件夹的匹配
- glob模式 :
- 简化了的正则表达式
- ***** : 匹配0~n个任意字符
- [abc] : 匹配任意一个括号中的字符
- ? : 匹配一个任意字符
- [0-9] : 匹配0到9(同理a-z是a到z)
- ****** : 匹配任意中间目录 : a/**/z可以匹配以a为最开始,z为最后的目录,如a/b/z
2.3 GitHub
2.3.1 开源
2.3.1.1 开源
- 概念 : 开放源代码
- 含义 : 代码是公开的
- 特点 : 任何人都可以去查看,修改和使用开源代码
2.3.1.2 闭源
- 概念 : 软件代码封闭的
- 含义 : 只有作者可以看到闭源软件的代码
- 特点 : 只有作者能修改
2.3.1.3 开源许可协议
- 为了限制使用者使用范围和保护作者权利
- 每个开源项目都要遵守的协议
- 常见协议 :
- BSD
- Apache Licence 2.0
- GPL ;
- 具有传染性
- 不允许修改后的衍生代码作为闭源的软件发布和销售
- 代表 : Linux
- LGPL
- MIT
- 在修改后的代码或者发行包中,必须包含原作者的许可信息
- 代表 : jQuery,Node.js
2.3.1.4 为什么要开源
- 我为人人,人人为我
- 给使用者更多控制权
- 让学习更容易
- 有真正的安全
2.3.1.5 开源托管平台
- 免费存放开源项目源代码的网站
- 代表 :
- GitHub : (最牛的)
- Gitlab : (对代码私有性支持较好,企业用户多)
- Gitee : (国产,访问快,纯中文,使用友好)
- 都只能托管Git管理的项目源代码
2.3.2 什么是GitHub
- 全球最大的开源项目托管平台
- 以Git作为唯一版本控制工具
- 可以关注自己喜欢的开源项目
- 为自己喜欢的项目做贡献
- 和开源项目作者讨论Bug和提需求(Issues)
- 把喜欢的项目复制一份作为自己的项目进行修改(Fork)
- 创建自己的开源项目
- 等等
- github不等于git
2.3.3 注册GitHub
- 访问官网: https://github/
- 点击Sign up按钮跳到注册页面
- 填写用户名邮箱密码
- 摆正验证图片
- 点击Greate account按钮注册新用户
- 登录邮箱,点击激活链接
2.3.4 新建空白远程仓库
-
3处填写仓库名字,最好由英文+下划线+版本组成
-
4处为仓库描述
-
创建成功的界面
2.3.5 访问远程仓库
- 两种方式 :
- HTTP : 零配置,但是每次访问仓库时,需要重复输入GitHub账号密码才能访问
- SSH : 需要配置,但是不需要重复输入Github账号密码
- 实际开发推荐使用SSH方式
2.3.5.1 HTTP访问
- 将本地仓库上传到GitHub
2.3.5.2 SSH访问
2.3.5.2.1 SSH key
- 作用 : 实现本地仓库和远程仓库之间免登录的加密数据传输
- 好处 : 免登录,传输加密
- 组成 :
- id_rsa : 私钥文件,存放于客户端的电脑中即可
- id_rsa.pub : 公钥文件,需要配置到GitHub中
2.3.5.2.2 生成SSH key
- 打开Git Bash
- 输入代码 : ssh-keygen -t rsa -b 4096 -C “GitHub注册邮箱”
- 连续敲三次回车
- 会自动在C/Users/用户名/.ssh目录中生成id_rsa和id_rsa.pub两个文件
2.3.5.2.3 配置SSH key
- 使用记事本打开id_rsa.pub,复制内容
- 登录GitHub
- 点击头像
- Settings
- SSH and GPG Keys
- New SSH key
- 将id_rsa.pub中的内容粘贴到key对应文本框中
- 在Title文本框中任意填写一个名称表示来处
2.3.5.2.4 检测配置成功
- 在Git Bash输入代码 : ssh -T git@github
- 显示 :
2.3.5.2.5 本地仓库上传GitHub
2.3.5.3 从远程仓库克隆到本地
- 打开Git Bash
- 输入代码 : git clone 远程仓库地址
2.4 Git分支
2.4.1 分支概念
-
分支概念 :
- 科幻电影里的平行宇宙
- 火影里的影分身
- 分支之间互不影响
- 分支合并后会获得每个分支的内容
-
作用
- 多人开发防止互相干扰
- 提高协同开发体验
- 建议每个开发者都基于分支进行项目功能的开发
-
主分支
- 初始化本地Git后会自动生成一个名为master的分支
- 用来保存和记录整个项目已完成的功能和代码
- 不允许程序员直接在master上修改代码,风险太高
-
功能分支
- 专门用来开发新功能的分支
- 临时从主分支上分出来的,开发完毕后合并回主分支上的分支
2.4.2 本地分支操作
代码 | 作用 |
---|---|
git branch | 查看分支列表(名字前有*的是当前分支) |
git branch 分支名 | 创建分支(执行完毕后仍处于原分支上) |
git branch -d 分支名 | 删除分支 |
git checkout 分支名 | 切换到分支上 |
git checkout -b 分支名 | 创建并切换到分支上 |
git merge 分支名 | 把代码中的分支合并到当前分支 |
- 当两个不同分支中对同一个文件进行了不同修改,Git无法合并我们需要打开文件手动合并,最好用vscode打开,因为vscode上有相应的合并功能
- 当我们合并完分支后,被合并的分支需要我们手动删除
2.4.3 远程分支操作
代码 | 作用 |
---|---|
git push -u 远程仓库别名 本地分支名:远程分支名 | 第一次将本地分支推送到远程 |
git push | 本地分支推送到远程 |
git remote show 远程仓库名 | 查看远程仓库分支列表 |
git checkout 远程分支名 | 跟踪分支,从远程下载分支到本地 |
git checkout -b 本地分支名 远程仓库名/远程分支名 | 下载到本地并重命名 |
git pull | 把远程分支最新代码下载到本地对应分支中 |
git push 远程仓库名 --delete 远程分支名 | 删除分支 |
3 Node.js
3.1 初识Node
3.1.1 Node.js与浏览器的区别
- 浏览器是JavaScript的前端运行环境
- Node.js是JavaScript的后端运行环境
- Node.js无法调用DOM和BOM等浏览器内置API
3.1.2 Node.js作用
- 基于Express框架快速构建Web项目
- 基于Electron框架构建跨平台桌面应用
- 基于restify框架快速构建API接口项目
- 读写数据库…
3.1.3 Node.js使用
- 查看已安装的Node.js版本号
- 打开终端输入命令 node -v,回车
- 快速打开终端
- wins+R,输入cmd
- Node.js环境中执行JavaScript代码
- 打开终端,输入node 要执行的文件路径
- 当前文件夹下打开终端 : shift+右键
- 终端中的快捷键 :
- 上箭头 : 快速定位到上一次执行的命令
- tab键 : 快速补全路径
- esc键 : 快速清空当前以输入的命令
- 输入cls : 清空终端
3.2 Node.js模块化开发
3.2.1 基本概念
3.2.1.1 什么是模块化
- 遵守固定的规则,把一个大文件拆成独立并相互依赖的多个小模块
- 好处 :
- 提高代码复用性
- 提高代码可维护性
- 实现按需加载
3.2.1.2 模块化规范
- 对代码进行模块化的拆分和组合的规则
- 好处 : 降低沟通成本
3.2.1.3 Node模块分类
- 内置模块 : Node.js官方提供的模块,无需下载
- 自定义模块 : 用户创建的每个js文件,都是自定义模块
- 第三方模块 : 由第三方开发出来的,使用前需下载
3.2.1.4 加载模块
-
模块内部可以使用require方法导入(加载)其他模块
-
require()方法加载其他模块时会执行被加载的模块中的代码
-
加载用户自定义模块可以省略.js后缀
3.2.1.5 模块作用域
-
与函数作用域类似
-
定义在模块中的变量,方法,只能在模块内部被访问
-
这种模块级别的访问限制就是模块作用域
-
好处 : 预防全局变量污染
3.2.1.6 向外共享模块作用域中的成员
-
module对象 : 每个js文件都有一个module对象,他里面存储了和当前模块有关的信息
-
module.export对象 : 自定义模块中,可以使用module.export对象把模块内的成员共享出去,给外界使用
-
外界用**require()**方法导入自定义模块时,会得到module.export所指向的对象
-
自定义模块中默认module.export={}
-
require()导入的对象永远以module.export指向的对象为准
-
export对象 :
- 简写module.export
- 同时设置了export和module.export的同一属性,以module.export为准
- 同时设置了export和module.export的不同属性,这些属性都会生效
-
建议再一个模块中只用同一种书写方式,不要混淆
3.2.1.7 Node.js的模块化规范
- 遵循CommonJS模块化规范
- CommonJS规定了模块的特性和各模块之间如何相互依赖
- CommonJS规定 :
- 每个模块内部module变量代表当前模块
- module是一个对象,他的export属性是对外接口
- 加载某个模块,实质上是加载模块的module.export属性
- **require()**方法用于加载模块
3.3 fs文件系统模块
3.3.1 什么是fs模块
- 官方提供的,用来操作文件的模块,提供了一系列方法和属性,来满足用户对文件操作的需求
- 读取文件 : fs.readFile()
- 写入文件 : fs.writeFile()
- 使用前需要先导入模块 : const fs = require(‘fs’)
3.3.2 读取文件
- 语法 : fs.readFile(path[,option],callback)
- 参数 :
- path : 必选参数,字符串,文件路径
- option; 可选参数,表示以什么编码格式读取文件
- callback : 必选参数,读取完成后的回调函数
- 函数内两个参数 :
- 第一个参数err : 读取失败提示信息
- 第二个参数result : 读取成功提示信息
const fs = require('fs')
fs.readFile('./files.1.txt','utf8',function(err,result) {
if(err){
return comsole.log('文件读取失败!' + err.mseeage)
}
console.log('文件读取成功,内容是:' + result)
})
3.3.3 写入文件
- 语法 : fs.writeFile(file,data[,option],callback)
- 参数 :
- file : 必选参数,字符串,文件路径
- data : 必选参数,写入的内容
- option; 可选参数,表示以什么编码格式读取文件
- callback : 必选参数,写入完成后的回调函数
- 函数内一个参数 :
- 参数err : 读取失败提示信息
3.3.4 回调函数参数值
-
读取成功 :
- err : null
- result : 读取结果
-
读取失败 :
- err : 错误对象
- result : undefined
-
写入成功 :
- err : null
-
写入失败 :
- err : 错误对象
3.3.5 路径拼接问题
- 以**./和…/**开头的相对路径,容易出现错误
- 原因 : 运行代码时会在执行node命令所在的目录拼接
- 解决方案 : 直接提供完整路径
3.4 path路径模块
3.4.1 什么是path模块
- Node.js官方提供的,用来处理路径的模块
- 路径片拼接 : path.join()
- 解析文件名 : path.basename()
- 使用前需要先导入模块 : const path = require(‘path’)
3.4.2 路径拼接
- 不要用+号拼接,尽量使用path.join()
- 语法 : path.join(path1,path2,path3,…)
const path = require('path')
const pathStr = path('/a','/b/c','../','./d','e')
console.log(pathStr)//输出\a\b\c\e
- __dirname : 当前目录
const path = require('path')
const pathStr = path(__dirname,'./files/1.txt')
console.log(pathStr)//输出当前文件所处目录+files/1.txt
3.4.3 获取文件名
- 语法 : path.basename(path)
const fpath = '/a/b/c/index.html'
var fullname = path.basename(fpath)
console.log(fullname)//输出index.html
var fullname = path.basename(fpath,'.html')
console.log(fullname)//输出index
3.4.4 获取文件扩展名
- 语法 : path.extname(path)
- 参数path : 路径,必写
- 返回值 : 扩展名字符串
3.5 http模块
3.5.1 什么是http模块
- Node.js官方提供的,用来创建Web服务器的模块
- 创建服务器 : http.crateServer()
- 使用前需要先导入模块 : const http = require(‘http’)
3.5.2 http模块作用
- 服务器上安装了web服务器软件
- http模块通过几行代码就可以手写一个服务器软件,不需要创建
3.5.3 IP地址
- 每台计算机的唯一地址
- 通常用十进制表示成**(a,b,c,d)形式,abcd都是0~255**之间的数
- 互联网中的每台Web服务器,都有自己的IP地址
- 本地地址 : 127.0.0.1
3.5.4 服务器概念
3.5.4.1 域名
- 域名 :
- 由于IP地址不直观不方便记忆,发明出的字符型地址方案
- 与IP地址一一对应
- 域名与IP地址的对应关系放在域名服务器上
- 域名服务器 : 提供IP地址与域名之间的转换服务的服务器
- localhost : 127.0.0.1的域名
3.5.4.2 端口号
- 不同服务对应电脑中的不同位置
- 通过端口号交给对应的Web服务处理
- 每个端口号不能同时被多个Web服务占用
- URL的80端口可以省略
3.5.4.3 创建最基本的Web服务器
3.5.4.3.1 步骤
- 导入http模块
const http = require('http')
- 调用createServer()
const server = http.createServer()
- 绑定request事件,监听客户端发送的网络请求
server.on('request',(req,res) => {
console.log('Someone visit our web server')
})
- 调用listen(端口号,回调方法)方法启动服务器
server.listen(80,() => {
console.log('http server running at http:/127.0.0.1')
})
3.5.4.3.2 req请求对象
- 想在事件处理函数中访问与客户端相关的数据和属性,使用如下方法
- 客户端请求地址 : req.url
- 客户端请求方式 : req.method
3.5.4.3.3 res请求对象
-
想在事件处理函数中访问与服务器相关的数据和属性,使用如下方法
-
向客户端发送指定内容,并结束这次请求的处理结果 : res.end(响应内容)
-
解决中文乱码 : res.setHeader(‘Content-Type’,‘text/html’,‘charset=utf-8’)
3.5.4.3.4 根据不同url响应不同html
-
获取请求的URL地址
-
设置默认响应内容为404 Not Found
-
判断用户请求的是否为**/或/index.html**首页
-
判断用户请求的是否为**/about.html**关于页面
-
设置Content-Type响应头,防止中文乱码
-
使用**res.end()**把内容响应给客户端
server.on('request',function(req,res) => {
const url = req.url;
let content = '<h1>404 Not Found</h1>'
if(url === '/' || url === '/index.html'){
content = '<h1>首页</h1>'
}else if( url === '/about.html') {
content = '<h1>关于页面</h1>'
}
res.setHeader('Content-Type','text/html','charset=utf-8')
res.end(content)
})
3.6 npm与包
3.6.1 包
-
包 : Node.js中的第三方模块
-
来源 : 由第三方团队或个人来发出来的,免费给所有人使用
-
包是基于内置模块封装出来的,提供了更高级,更方便的API,极大提高开发效率
-
包和内置模块的关系 : 类似于JQuery和浏览器内置API之间的关系
-
从哪下包 :
- 国外公司npm,Inc.的网站https://www.npmjs/是全球最大的包共享平台,可以从这个网站搜索到需要的包(搜索包)
- 该公司提供了一个地址为https://www.registry.npmjs/的服务器,对外共享所有的包(下载包)
3.6.2 npm包管理工具
3.6.2.1 npm命令
代码 | 作用 |
---|---|
npm -v | 查看npm 版本 |
npm init | 初始化,成功后出现一个package.json文件 |
npm init -y | 初始化并跳过问答界面 |
npm install | 根据package.json下载项目所需包 |
npm install 包名 | 安装指定的包 |
npm i 包名 | npm install 包名 简写 |
npm i 包名@版本 | 安装指定版本的包 |
npm i -g 包名 | 安装指定的包并设置全局可用 |
npm install 包名 --save | 安装的包需要发布到生产环境,出现在package.json的dependencise属性中 |
npm install 包名 --S | npm install 包名 --save 简写 |
npm install 包名 --save-dev | 安装的包只用于开发环境,出现在package.json的devDependencise属性中 |
npm install 包名 -D | npm install 包名 --save-dev 简写 |
npm list | 查看当前目录下已安装的包 |
npm list -g | 查看全局已安装的包 |
npm --help | 查看npm帮助命令 |
npm update 包名 | 更新指定包 |
npm uninstall 包名 | 卸载指定包 |
npm config list | 查看配置信息 |
npm 指定命令 --help | 查看指定命令的帮助 |
npm info 指定包名 | 查看远程npm上包的所有版本信息 |
npm root | 查看当前包安装路径 |
npm root -g | 查看全局的包的安装路径 |
npm ls 包名 | 查看本地安装的指定包及版本信息,没有显示empty |
npm ls 包名 -g | 查看全局安装的指定包及版本信息,没有显示empty |
npm config get registry | 查看当前下载源 |
npm config set registry= 地址 | 修改包的下载源 |
3.6.2.2 初次装包
-
初次装包后项目文件夹下多了node_modules文件夹和package-lock.json配置文件
-
node_modules文件夹 : 存放所有以安装到项目的包,require()导入第三方包就是从这里查找
-
package-lock.json配置文件 : 记录node_modules中每一个包的信息(名字,版本,下载地址等)
-
不要手动修改这两个文件,npm会自动维护
3.6.2.3 包的语义化版本规范
- 点分十进制 : 总共三个数字(eg : 2.24.0)
- 第一个数字 : 大版本
- 第二个数字 : 功能版本
- 第三个数字 : Bug修复版本
- 规则 : 前面的版本号增长了,后边的版本号清零
3.6.2.4 包管理配置文件
-
在项目根目录中,必须提供一个package.json配置文件,记录项目信息
-
项目名称,版本号,描述
-
项目包含包
-
包的类别
-
第三方包文件过大,不方便共享,所以共享时删除node_modules,由对方自己去下载package.json里记录的包
-
开发中要把node_modules添加到**.gitignore**忽略文件中
-
快速创建命令 : npm init -y
- 只能在英文目录下运行
- 下载包后,npm会自动记录到package.json中
-
dependencies节点 :
- 记录安装了哪些包
- npm install会根据该节点下载所需包
3.6.2.5 解决下载慢问题
-
npm默认从国外的https://www.registry.npmjs/网站下载,需要走海底光缆,速度慢
-
淘宝镜像 : 淘宝在国内搭建了一个服务器,专门把国外官方服务器上的包同步到国内服务器,然后在国内提供下载服务
-
镜像 : 一种文件存储形式,一个磁盘上的数据在另一个磁盘上存在的一个完全相同副本
-
淘宝镜像地址 : https://registry.npm.taobao/
3.6.2.6 nrm
- 切换下载源小工具
代码 | 作用 |
---|---|
npm -i nrm -g | 安装nrm并设置全局可用 |
nrm ls | 查看可用的镜像源 |
nrm use taobao | 切换到淘宝镜像 |
3.6.2.7 格式化时间
- 引入包moment
- 参考API对时间格式化
3.6.2.8 md转html
- i5ting_toc小插件
代码 | 作用 |
---|---|
npm i -g i5ting_toc | 下载插件 |
i5ting_toc -f 文件路径 -o | md转html |
3.6.3 包的分类
3.6.3.1 项目包
- 安装到项目node_modules中的包
- 分类 :
- 开发依赖包 : devDependencies节点中的包
- 核心依赖包 : dependencies节点中的包
3.6.3.2 全局包
-
npm i 包名 -g命令下载的包是全局包
-
全局包会下载到C:\User\用户\AppData\Roaming\npm\node_modules目录下
-
只用工具包才有必要设置全局安装
3.6.4 包结构
- 包必须以单独的目录存在
- 包的顶级目录下必须包含package.json包管理配置文件
- package.json中必须包含name,version,main三个属性,分别表示包的名字,版本,入口
3.7 模块加载机制
3.7.1 优先从缓存加载
- 模块第一次加载后会被缓存,多次调用require()不会导致代码被执行多次,提高模块加载效率
3.7.2 内置模块加载机制
- 内置模块加载优先级最高
- 名字相同的模块,调用时会先选择内置模块来执行
3.7.3 自定义模块加载机制
- 使用require加载自定义模块时,必须指定以**./或…/开头的路径标识符**,否则会被当做内置模块或第三方模块来加载
- 路径省略文件扩展名,node的加载顺序 :
- 按照确切文件名进行加载
- 补全.js进行加载
- 补全.json进行加载
- 补全,nodd进行加载
- 加载失败报错
3.7.4 第三方模块加载机制
- 从当前模块的父目录中查找**/node_modules**文件夹并加载第三方模块
- 找不到则移动到上一级父目录查找**/node_modules**文件夹并加载第三方模块
- 最终达到磁盘根目录,找不到报错
3.7.5 目录作为模块
- 把目录传递给require,有三种加载方式 :
- 在被加载的目录下查找package,json文件,并查找main属性,作为require入口
- 无package,json或者无main,会查找index.js进行加载
- 查找失败报错
4 Express
4.1 Express基础
4.1.1 Express简介
-
什么是Express :
- 基于Node.js平台,快速,开放,极简的Web开发框架
-
Express本质 : npm上的第三方包,提供了快速创建Web服务器的便捷方法
-
官网 : http://www.expressjs/
-
Express作用 : 快速创建Web网站服务器和API接口服务器
-
不用Express也能使用Node.js的原生http模块创建Web服务器
-
但是http内置模块使用复杂,开发效率低
-
Express是在http模块上封装出来的,极大提高开发效率
-
Express与http模块的关系就如同JQuery和浏览器的关系
4.1.2 基本使用
4.1.2.1 监听GET请求
- 语法 : app.get(URL,function(req,res){})
- 参数 :
- URL : 请求地址
- req : 请求对象
- res : 响应对象
4.1.2.2 监听POST请求
- 语法 : app.post(URL,function(req,res){})
- 参数 :
- URL : 请求地址
- req : 请求对象
- res : 响应对象
4.1.2.3 响应内容给客户端
- 语法 : res.send(内容)
- 写在处理函数function(req,res){}里
4.1.2.4 获取URL中携带的查询参数
- 语法 : req.query
- req.query默认是一个空对象
- 当用户使用**?name=zs&password=123**这种查询字符串形式把参数发送到服务器
- 可以通过req.query接收访问
- 此时req.query.name=zs
4.1.2.5 获取URL动态参数
-
语法 : req.params
-
URL地址中可以使用**:参数名**的形式动态匹配参数值
-
req.params默认是一个空对象
-
当用户使用**?:name&:password**这种动态匹配形式把参数发送到服务器
-
可以通过req.params接收访问
4.1.2.6 托管静态资源
- 语法 : app.use(express.static(‘public’))
- 可以访问public目录中的所有文件
- Express在指定的静态目录中查找文件,并对外提供资源的访问路径,因此,存放静态文件的目录名不会出现在URL中
- 托管多个静态资源目录 : 调用多次该函数,express.static会根据顺序查找文件
- 挂载路径前缀 :
- 语法 : app.use(‘/public’,express.static(‘public’))
- 访问public下的文件时可以加上/public来访问
4.1.2.7 创建基本Web服务器
- 导入express
const express = require('express')
- 创建web服务器
const app = express()
- 调用**listen(端口号,回调函数)**来启动服务器
app.listen(80,() => {
console.log('express server running at http://127.0.0.1')
})
4.1.2.8 nodemon
- 调试Node.js项目的时候,修改了代码需要频繁关闭服务器再开启
- nodemon可以监听项目文件的变动,自动重启项目
代码 | 作用 |
---|---|
npm i -g nodemon | 下载全局包 |
nodemon app.js | 运行文件 |
4.2 Express路由
4.2.1 路由的概念
-
客户端请求和服务器处理函数之间的映射关系
-
组成 :
- 请求类型
- 请求URL地址
- 处理函数
-
app.get(URL,function(){})就是一个路由
-
路由匹配过程 :
- 按照定义的先后顺序匹配
- 请求类型和请求的URL同时匹配成功才调用处理函数
4.2.2 路由的使用
- 为了方便模块化的管理,Express不建议将路由直接挂载到app上,而是抽离为单独的模块
- 步骤 :
- 创建对应.js文件
- 调用**express.Router()**函数创建路由对象
- 向路由对象上挂载具体路由
- 调用modules.export向外共享
- 使用**app.use()**函数注册路由模块
4.2.3 创建路由模块
//导入express
const express = require('express')
//创建对象
const router = express.Router()
//挂载路由
router.get(URL,function(req,res){
res.send('Get URL')
})
router.post(URL,function(req,res){
res.send('Add new URL')
})
//向外共享
module.export = router
4.2.4 注册路由模块
//导入router
const router = require('模块文件路径')
//注册
app.use(router)
//添加前缀
app.use('/api',router)
4.3 Express中间件
4.3.1 中间件概念
4.3.1.1 中间件的定义
- 业务流程的中间处理环节
4.3.1.2 中间件的调用流程
- 一个请求到达Express服务器后,可以连续调用多个中间件,从而完成对这次请求的预处理
4.3.1.3 中间件的格式
- 中间件本质上是一个function处理函数
- 中间件的形参列表中必须包含next参数
- 路由处理函数只需包含req,res
4.3.1.4 next函数作用
- 实现多个中间件连续调用的关键
- 把流转关系交给下一个中间件或者路由
4.3.1.5 中间件作用
- 多个中间件之间共用一个req和res
- 可以在上游的中间件中,统一为req或者res添加自定义属性和方法,供下游中间件使用
4.3.2 定义中间件
4.3.2.1 定义中间件函数
const mw = function(req,res,next) {
console.log('这是一个中间件函数')
next()
}
4.3.2.2 定义全局生效中间件
- 客户发送任何请求,到达服务器后都会触发的中间件
- 语法 : app.use(中间件处理函数)
const mw = function(req,res,next) {
console.log('这是一个中间件函数')
next()
}
app.use(mw)
4.3.2.3 简写定义全局中间件
app.use(function(req,res,next) {
console.log('这是一个中间件函数')
next()
})
4.3.2.4 定义多个全局中间件
- 使用app.use()连续定义
- 客户端请求到达后会按照定义的先后顺序依次调用
4.3.2.5 定义局部生效中间件
- 不使用app.use()定义的中间件是局部生效的中间件
const mw = function(req,res,next) {
console.log('这是一个中间件函数')
next()
}
app.get('/',mw,function(req,res) => {
res.send('调用局部生效的中间件')
})
4.3.2.6 定义多个局部中间件
- 方法一
app.get('/',mw1,mw2,function(req,res) => {
res.send('调用局部生效的中间件')
})
- 方法二
app.get('/',[mw1,mw2],function(req,res) => {
res.send('调用局部生效的中间件')
})
4.3.3 中间件注意事项
- 一定要注册在路由之前
- 客户端发送请求可以连续调用多个中间件
- 执行完毕业务代码后要添加**next()**函数
- 防止代码逻辑混乱,调用next()后该中间件内不要再写其他代码
- 连续调用多个中间件,共享req和res
4.3.4 中间件分类
- 应用级别中间件
- 路由级别中间件
- 错误级别中间件
- Express内置中间件
- 第三方中间件
4.3.4.1 应用级别中间件
- 通过app.use(),app.get(),app.post,绑定到app实例上的中间件
const mw = function(req,res,next) {
console.log('这是一个中间件函数')
next()
}
app.get('/',mw,function(req,res) => {
res.send('调用局部生效的中间件')
})
4.3.4.2 路由级别中间件
- 绑定到express.Router()实例上的中间件
const app = express()
const router = express.Router()
router.use(function(req,res,next) {
console.log('这是一个中间件函数')
next()
})
app.use(router)
4.3.4.3 错误级别中间件
- 作用 : 专门捕获项目中所发生的异常错误,防止项目异常崩溃
- 格式 : function中必须有四个参数,依次是err,req,res,next
- 位置 : 注册在所有路由之后
app.get('/',mw,function(req,res) => {
throw new Error('服务器内部发生错误')
res.send('调用局部生效的中间件')
})
app.use(function(err,req,res,next) => {
console.log('发生了错误'+err.message)
res.send('Error!'+err.message)
})
4.3.4.4 内置中间件
- Express内置三个常用中间件 :
- express.static : 快速托管静态资源的内置中间件
- express.json : 解析JSON格式的请求体数据(有兼容性,4.16.0+版本可用)
- express.urlencoded : 解析URL-encoded格式的请求体数据(有兼容性,4.16.0+版本可用)
//配置解析application/json格式数据内置中间件
app.use(express.json())
//配置解析application/x-www-form-urlencoded格式数据内置中间件
app.use(express.urlencoded({extended: false}))
- req.body属性 : 接收客户端发过来的请求体数据
4.3.4.5 第三方中间件
- 按需下载并配置
4.4 Express写接口
4.4.1 CORS跨域资源共享
4.4.1.1 什么是cors
- 由一些列HTTP响应头组成,这些响应头决定浏览器是否阻止前端JS代码跨域获取资源
- 如果接口配置了CORS相关HTTP响应头,就可以解除浏览器跨域访问限制
4.4.1.2 使用CORS中间件
- 安装中间件
npm install cors
- 导入中间件
const cors = require('cors')
- 配置中间件(注册路由之前)
app.use(cors())
4.4.1.3 注意事项
- CORS主要在服务器端进行配置,客户端无需做任何额外的配置
- 具有兼容性,支持XMLHttpRequest Level2的浏览器
4.4.1.4 CORS响应头部ACAO
-
Access-Control-Allow-Origin属性 : 接收范围
-
如果指定了Access-Control-Allow-Origin属性值为通配符*,表示允许来自任何域的请求
res.setHeader('Access-Control-Allow-Origin','*')
4.4.1.5 CORS响应头部ACAH
-
Access-Control-Allow-Headers : 接收请求头
-
默认情况下CORS仅支持客户端发送九个请求头
- Accept,Accept-Language,Content-Language,DPR,Downlink,Save-Data,Viewport-Width,Width
- Content-Type(值仅限于text/plain,multipart/form-data,application/x-www-form-urlencoded三者之一)
-
发送额外请求,需要在服务器端对额外的请求头进行声明,否则请求失败
//允许客户端额外向服务器端发送Content-Type,X-Custom-Header
res.setHeader('Access-Control-Allow-Headers','Content-Type','X-Custom-Header')
4.4.1.6 CORS响应头部ACAM
- Access-Control-Allow-Methods : 接收请求方式
- 默认情况下CORS仅支持客户端发起GET,POST,HEAD请求
- 客户端希望通过PUT,DELETE等方式请求服务器的资源,需要在服务器上指明实际请求所允许使用的HTTP方式
//只允许客户端发送GET,POST,DELETE,HEAD请求方法
res.setHeader('Access-Control-Allow-Methods','POST,GET,DELETE,HEAD')
//允许所有请求方法
res.setHeader('Access-Control-Allow-Methods','*')
4.4.1.7 简单请求
- 请求方式 : GET,POST,HEAD三者之一
- 请求头部信息 : 不超过无自定义头部字段,九种默认字段这几种
4.4.1.8 预检请求
- 请求方式 : GET,POST,HEAD三者之外的请求
- 请求头部信息 : 包含自定义头部字段
- 向服务器发送了application/json格式的数据
- 预检请求步骤 :
- 浏览器先发送OPTION请求进行预检,以获知服务器是否允许该实际请求
- 响应预检请求成功后,才会发送真正的请求,携带真正的数据
4.4.1.9 请求区别
- 简单请求 : 服务器与客户端之间只发生一次请求
- 预检请求 : 服务区与客户端之间发生两次请求
4.4.2 JSONP接口
4.4.2.1 回顾JSONP
- 浏览器通过script标签上的src属性请求服务器上的数据,同时服务器返回一个函数的调用
- 特点 :
- 不属于真正的Ajax
- 仅支持GET请求
4.4.2.2 实现JSONP接口步骤
- 获取客户端发送过来的回调函数的名字
- 得到要通过JSONP形式发送给客户端的数据
- 根据数据拼接出一个函数调用的字符串
- 把字符串响应给scirpt标签进行解析执行
app.get('/api/jsonp',(req,res) => {
//获取客户端发送过来的回调函数的名字
const funcName = req.query.callback
//得到要通过JSONP形式发送给客户端的数据
const data = {name: 'zs',age: 20}
//根据数据拼接出一个函数调用的字符串
const scriptStr = `${funcName}(${JSON.stringify(data)})`
//把字符串响应给scirpt标签进行解析执行
res.send(scriptStr)
})
4.4.2.3 网页中使用JQuery发起JSONP请求
- 调用$.ajax()函数
- 提供JSONP配置选项
$('#btnJSONP').on('click',function() {
$.ajax({
method: 'GET',
url: 'http://127.0.0.1/api/jsonp',
dataType: 'jsonp', //发起JSONP请求
success: function(res) {
console.log(res)
}
})
})
4.4.2.4 注意事项
-
如果项目中已经配置了CORS,为了防止冲突,必须在配置CORS中间件之前声明JSONP接口
-
否则JSONP接口会被处理成CORS接口
4.5 Express操作数据库
4.5.1 步骤
-
安装操作MySQL的第三方模块mysql
-
连接数据库
-
执行mysql语句
4.5.2 安装mysql模块
- 语法 : npm i mysql
4.5.3 配置mysql模块(连接数据库)
- 导入模块
const mysql = require('mysql')
- 建立连接
const jsdbc = mysql.createPool({
host: '127.0.0.0' //数据库IP地址
user: 'root' //登录账号
password: 'l978756990221' //登录密码
database: 'student' //指定要操作的数据库
})
4.5.4 操作语句
4.5.4.1 查询数据
jsdbc.query('SELECT * FROM 表名',(err,results) => {
//操作失败
if(err) return console.log(err.message)
//操作成功
console.log(results)
})
4.5.4.2 插入数据
- 定义插入对象
const user = {username: 'lxl',paaword: '123456'}
- 定义SQL语句,?表示占位符
const sqlStr = 'INSERT INTO 表名 (username,password) VALUES (?,?)'
- 使用数组形式依次为?占位符填值
jsdbc.query(sqlStr,[user.username,user.password],(err,results) => {
//操作失败
if(err) return console.log(err.message)
//操作成功
if(results.affectedRows === 1) {console.log('操作成功')}
})
4.5.4.3 插入简写
- 注意 : 数据对象的每个属性和表中的字段一一对应
const user = {username: 'lxl',paaword: '123456'}
const sqlStr = 'INSERT INTO 表名 SET ?'
jsdbc.query(sqlStr,user,(err,results) => {
//操作失败
if(err) return console.log(err.message)
//操作成功
if(results.affectedRows === 1) {console.log('操作成功')}
})
4.5.4.4 更新数据
- 定义更新的数据对象
const user = {id: 7,username: 'lxl',paaword: '123456'}
- 定义SQL语句,?表示占位符
const sqlStr = 'UPDATE 表名 SET username=?,password=? WHERE id=?'
- 使用数组形式依次为?占位符填值
jsdbc.query(sqlStr,[user.username,user.password,user.id],(err,results) => {
//操作失败
if(err) return console.log(err.message)
//操作成功
if(results.affectedRows === 1) {console.log('操作成功')}
})
4.5.4.5 更新简写
- 注意 : 数据对象的每个属性和表中的字段一一对应
const user = {id: 7,username: 'lxl',paaword: '123456'}
const sqlStr = 'UPDATE 表名 SET ? WHERE id=?'
jsdbc.query(sqlStr,[user,user.id],(err,results) => {
//操作失败
if(err) return console.log(err.message)
//操作成功
if(results.affectedRows === 1) {console.log('操作成功')}
})
4.5.4.6 删除数据
- 定义SQL语句,?表示占位符
const sqlStr = 'DELETE FROM 表名 WHERE id=?'
- 执行语句为?占位符填值
jsdbc.query(sqlStr,7,(err,results) => {
//操作失败
if(err) return console.log(err.message)
//操作成功
if(results.affectedRows === 1) {console.log('操作成功')}
})
4.5.4.7 标记删除
- DELETE语句会真正把数据从数据库删除
- 保险起见推荐使用标记删除形式
- 标记删除 : 在表中设置status状态字段,标记当前数据是否被删除
- 当用户删除数据时,不进行删除操作,而是更新status字段的值表示数据被删除
4.6 前后端身份认证
4.6.1 Web开发模式
4.6.1.1 服务器渲染的Web开发模式
-
服务器渲染 : 服务器发送给客户端的HTML页面,是在服务器通过字符串的拼接,动态生成的
-
所以需要使用ajax这样的技术额外请求页面的数据
-
优点 :
- 前端耗时少 : 服务器负责生成,浏览器负责渲染,尤其是移动端,更省电
- 有利于SEO : 服务器响应的是完整HTML页面,所以爬取更容易
-
缺点 :
- 占用服务器资源 : 服务器完成HTML页面内容拼接,请求较多会对服务器造成访问压力
- 不利于前后端分离,开发效率低 : 使用服务器渲染,无法进行分工合作
4.6.1.2 前后端分离的Web开发模式
- 前后端分离 : 后端负责提供API接口,前端使用Ajax调用接口
- 依赖于Ajax技术的广泛使用
- 优点 :
- 开发体验好 : 前端专注UI开发,后端专注API开发,分工明确
- 用户体验好 : Ajax技术的广泛使用,极大提高了用户体验,轻松实现界面的局部刷新
- 减轻服务器渲染压力 : 页面最终是在每个用户的浏览器中生成
- 缺点 :
- 不利于SEO
- 解决方案 : 前端框架的SSR技术
4.6.1.3 如何选择开发模式
- 不谈业务场景而盲目选择使用何种开发模式都是耍流氓
- 服务器渲染的Web开发模式 : 企业级网站
- 前后端分离的Web开发模式 : 后台管理项目
- 为了兼顾首页渲染速度和前后端分离的开发效率,一些网站采用首屏服务器渲染模式+其他页面前后端分离
4.6.2 身份认证概念
4.6.2.1 什么是身份认证
- 又称身份验证,鉴权,指通过一定手段,完成对用户身份的确认
- 生活中的身份证
- 手机验证码,邮箱密码登录,二维码登录
4.6.2.2 身份认证目的
- 确认当前声称为某种身份的用户,确实是所声称的用户
4.6.2.3 认证机制
- 服务器渲染模式 : Session认证机制
- 前后端分离模式 : JWT认证机制
4.6.3 Session认证机制
4.6.3.1 Session原理
- HTTP协议无状态性 : 客户端每次请求都是独立的,多个请求之间无联系,服务器不会主动保留每次请求的状态
- 突破无状态限制 : 使用Cookie
- 提高安全性 : Session工作原理
4.6.3.2 Cookie概念
- 存储在用户浏览器中的一段不超过4k的字符串
- 由一个名称,一个值,几个用于控制Cookie有效期,安全性,使用范围的可选属性组成
- 不同域名下的Cookie各自独立,客户端发起请求时,会自动把当前域名下未过期Cookie一同发送到服务器
4.6.3.3 Cookie特性
- 自动发送
- 域名独立
- 过期时限
- 4KB限制
4.6.3.4 Cookie作用
- 客户端第一次请求时,服务器通过响应头的形式,向客户端发送一个身份认证Cookie
- 客户端自动将Cookie保存到浏览器中
- 之后的每次请求服务器时,浏览器自动将身份认证的Cookie通过请求头的形式发送给服务器
- 服务器即可验明客户端身份
4.6.3.5 Cookie不具有安全性
- Cookie是在浏览器中存储的,因此浏览器中提供了读写Cookie的API,因此Cookie容易被伪造
- 不要将重要且隐私的数据存储到Cookie中
4.6.3.6 Session工作原理
- 客户端第一次请求时,验证账号密码,登录成功后将用户信息存储到服务器中,同时生成对应的Cookie字符串
- 浏览器自动把Cookie存储到当前域名下
- 客户端再次请求,通过请求头把Cookie发送到服务器
- 服务器根据Cookie查找用户信息并验证
- 服务器响应给客户端指定内容
4.6.3.7 Express中使用Session
- 安装express-session中间件
npm install express-session
- 配置express-session中间件
//导入中间件
const session = require('express-session')
//配置中间件
app.use(session({
secret: 'keyboard cat', //secret属性值可以为任意字符串
resave: false, //固定写法
saveUninitialized: true //固定写法
}))
- 向session中存储数据(通过req.session来访问和使用对象)
app.post('/api/login',(req,res) => {
//判断用户提交的登录信息是否正确
if(req.body.username !=='lxl' || req.body.password !== '123456') {
return res.send({status: 1,msg: '登陆失败'})
}
//将用户信息存储到Session中
req.session.user = req.body
//将用户的登陆状态存储到Session中
req.session.islogin = true
res.send({statue: 0,msg: '登陆成功'})
})
- 从session中读取数据(通过req.session来访问和使用对象)
//获取用户姓名的接口
app.get('/api/username',(req,res) => {
//判断用户是否登录
if(!req.session.islogin) {
return res.send({status: 1,msg: 'fail'})
}
res.send({status: 0,msg: 'success',username: req.session.user.username})
})
- 清空session
//退出登录的接口
app.post('/api/logout',(req,res) => {
//清空当前客户端对应的session信息
req.session.destroy()
res.send({status: 0,msg: '退出登陆成功'})
})
4.6.3.8 Session的局限性
- 需要配合Cookie才能实现
- Cookie不支持跨域,涉及跨域请求时要做很多配置
4.6.4 JWT认证机制
4.6.4.1 JWT概念
- 目前最流行的跨域认证解决方案(JSON Web Token)
4.6.4.2 JWT工作原理
-
客户端提交登录信息
-
服务器验证登录,通过后将用户信息经加密生成Token字符串
-
服务器将生成的Token响应发送给客户端
-
客户端将Token存储到LocalStorage或SessionStorage中
-
客户端再次发起请求,通过请求头的Authorization字段将Token发给服务器
-
服务器把Token还原成用户信息对象
-
用户身份验证成功后,服务器把指定内容响应给客户端
-
注意 :
- 用户的信息通过Token字符串的形式存储在客户端中
- 服务器通过还原Token字符串的形式认证用户身份
4.6.4.3 JWT组成部分
- 由三部分组成 :
- Header(头部) : 保证安全性
- Payload(有效荷载) : 用户信息经过加密后生成的字符串
- Signature(签名) : 保证安全性
- 三者之间用英文的点分隔
Header.Payload.Signature
4.6.4.4 JWT使用方式
- 客户端收到服务器返回的JWT后,通常保存在LocalStorage或SessionStorage中
- 以后每次客户端与服务器通信,都要带上这个JWT字符串,从而进行身份验证
- 推荐把JWT放在HTTP请求头的Authorization字段中
Authorization: Bearer <token>
4.6.4.5 Express中使用JWT
- 安装JWT相关包
- jsonwebtoken : 生成JWT字符串
- express-jwt : 将JWT字符串解析还原成JSON对象
npm install jsonwebtoken exoress-jwt
- 导入相关包
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
- 定义secret密钥
- 为了保证JWT字符串的安全性,防止JWT在网络传输过程中被人破解,我们需要专门定义一个用于加密和破解的secret秘钥
- 生成JWT字符串的时候,需要使用secret秘钥对用户信息进行加密,最终得到加密好的JWT字符串
- 当解析JWT字符串还原成JSON对象的时候,需要使用secret秘钥进行解密
- secret本质 : 一个字符串
const secretKey = 'lxl No1 ^_^'
- 登录成功后生成JWT字符串
- 调用jsonwebtoken的jwt.sign()生成JWT字符串
- jwt.sign()三个参数 : 用户信息对象,加密密钥,配置对象
app.post('/api/login',(req,res) => {
//判断用户提交的登录信息是否正确
if(req.body.username !=='lxl' || req.body.password !== '123456') {
return res.send({status: 1,msg: '登陆失败'})
}
//用户登录成功后生成JWT字符串通过token响应给客户端
res.send({
statue: 0,
msg: '登陆成功',
//调用jwt.sign()生成JWT字符串
token: jwt.sign({username: userinfo.username},secretKey,{expiresIn: '30s'})
})
})
app.post('/api/login',(req,res) => {
//判断用户提交的登录信息是否正确
if(req.body.username !=='lxl' || req.body.password !== '123456') {
return res.send({status: 1,msg: '登陆失败'})
}
//用户登录成功后生成JWT字符串通过token响应给客户端
const tokenStr = jwt.sign({username: userinfo.username},secretKey,{expiresIn: '30s'})
res.send({
statue: 0,
msg: '登陆成功',
//调用jwt.sign()生成JWT字符串
token: tokenStr
})
})
- 把JWT字符串还原成JSON对象
- 客户端每次访问有权限接口时,都需要主动通过请求头中的Authorization字段,将Token字符串发送给服务器进行认证
- 此时服务器通过express-jwt中间件自动将客户端发送过来的Token解析还原成JSON对象
//app.use()注册中间件
//expressJWT()为解析功能的中间件,需要穿第一个对象类型的参数来指定秘钥
//{secret: secretKey}为上文自定义的秘钥
//.unless()指定哪些接口不需要访问权限
//{path: [/^\/api\//]}为接口路径正则表达式(标有转义字符)
app.use(expressJWT({secret: secretKey}).unless({path: [/^\/api\//]}))
- 使用req.user获取用户信息
- express-jwt配置成功后,即可在那些有权限的接口中使用req.user对象访问JWT字符串中的用户信息
//获取用户姓名的接口
app.get('/api/getinfo',(req,res) => {
console.log(req.user)
//判断用户是否登录
if(!req.session.islogin) {
return res.send({status: 1,msg: 'fail'})
}
res.send({
status: 0,
msg: 'success',
data: req.user
})
})
- 捕获解析失败后产生的错误
- 解析字符串时,如果Token过期或不合法,会产生一个解析失败的错误,影响正常运行
- 可以通过Express错误中间件来捕获处理
app.use((err,req,res,next) => {
//token解析失败导致的错误
if(err.name === 'UnauthorizedError') {
return res.send({status: 401,message: '无效的token'})
}
//其它原因导致的错误
res.send({status: 500,message: '未知错误'})
})
4.6.4.5 Express中使用JWT
- 安装JWT相关包
- jsonwebtoken : 生成JWT字符串
- express-jwt : 将JWT字符串解析还原成JSON对象
npm install jsonwebtoken exoress-jwt
- 导入相关包
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
- 定义secret密钥
- 为了保证JWT字符串的安全性,防止JWT在网络传输过程中被人破解,我们需要专门定义一个用于加密和破解的secret秘钥
- 生成JWT字符串的时候,需要使用secret秘钥对用户信息进行加密,最终得到加密好的JWT字符串
- 当解析JWT字符串还原成JSON对象的时候,需要使用secret秘钥进行解密
- secret本质 : 一个字符串
const secretKey = 'lxl No1 ^_^'
- 登录成功后生成JWT字符串
- 调用jsonwebtoken的jwt.sign()生成JWT字符串
- jwt.sign()三个参数 : 用户信息对象,加密密钥,配置对象
app.post('/api/login',(req,res) => {
//判断用户提交的登录信息是否正确
if(req.body.username !=='lxl' || req.body.password !== '123456') {
return res.send({status: 1,msg: '登陆失败'})
}
//用户登录成功后生成JWT字符串通过token响应给客户端
res.send({
statue: 0,
msg: '登陆成功',
//调用jwt.sign()生成JWT字符串
token: jwt.sign({username: userinfo.username},secretKey,{expiresIn: '30s'})
})
})
app.post('/api/login',(req,res) => {
//判断用户提交的登录信息是否正确
if(req.body.username !=='lxl' || req.body.password !== '123456') {
return res.send({status: 1,msg: '登陆失败'})
}
//用户登录成功后生成JWT字符串通过token响应给客户端
const tokenStr = jwt.sign({username: userinfo.username},secretKey,{expiresIn: '30s'})
res.send({
statue: 0,
msg: '登陆成功',
//调用jwt.sign()生成JWT字符串
token: tokenStr
})
})
- 把JWT字符串还原成JSON对象
- 客户端每次访问有权限接口时,都需要主动通过请求头中的Authorization字段,将Token字符串发送给服务器进行认证
- 此时服务器通过express-jwt中间件自动将客户端发送过来的Token解析还原成JSON对象
//app.use()注册中间件
//expressJWT()为解析功能的中间件,需要穿第一个对象类型的参数来指定秘钥
//{secret: secretKey}为上文自定义的秘钥
//.unless()指定哪些接口不需要访问权限
//{path: [/^\/api\//]}为接口路径正则表达式(标有转义字符)
app.use(expressJWT({secret: secretKey}).unless({path: [/^\/api\//]}))
- 使用req.user获取用户信息
- express-jwt配置成功后,即可在那些有权限的接口中使用req.user对象访问JWT字符串中的用户信息
//获取用户姓名的接口
app.get('/api/getinfo',(req,res) => {
console.log(req.user)
//判断用户是否登录
if(!req.session.islogin) {
return res.send({status: 1,msg: 'fail'})
}
res.send({
status: 0,
msg: 'success',
data: req.user
})
})
- 捕获解析失败后产生的错误
- 解析字符串时,如果Token过期或不合法,会产生一个解析失败的错误,影响正常运行
- 可以通过Express错误中间件来捕获处理
app.use((err,req,res,next) => {
//token解析失败导致的错误
if(err.name === 'UnauthorizedError') {
return res.send({status: 401,message: '无效的token'})
}
//其它原因导致的错误
res.send({status: 500,message: '未知错误'})
})
本文标签: AjaxNode
版权声明:本文标题:AjaxNode 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1729726420a1211421.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论