admin管理员组

文章数量:1656157

文章目录

  • 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])
  • 参数 :
参数名类型是否必选说明
urlstring请求的地址
dataobject指定要请求的元素参数(eg : id=1)
callbackfunction请求成功的回调函数
1.2.1.2 $.post()语法
  • 专门用来发起post提交
  • 语法 :
$.post(url,[data],[callback])
参数名类型是否必选说明
urlstring提交的地址
dataobject指定要提交的数据
callbackfunction提交成功的回调函数
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属性
属性描述
actionURL地址向何处发送表单数据
methodget/post用什么方式提交
enctypeapplication/x-www-form-urlencoded multipart/form-data
text/plain
发送表单之前如何编码
targetblank/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(对象);**函数
      • 输出**‘对象’**
  • 序列化 : 数据对象转化成字符串
  • 反序列化 : 字符串转化成数据对象
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沿着到目标资源的路径执行一个消息环回测试
PATCHPUT的补充,用来对已知资源进行局部更新
1.2.6.5 HTTP响应状态码
  • 用来标识响应的状态
  • 会随着响应消息一起被发送到客户端浏览器
  • 浏览器根据服务器返回的响应状态码,就知道这次请求是否成功
  • 组成 : 由三个十进制数字组成 :
    • 第一个数字定义了状态码类型
    • 后两个用来对状态码进行细分
  • 五类状态码 :
分类描述
1**信息,服务器收到请求,需要请求这继续执行操作(实际开发中很少见)
2**成功,操作被成功接收并处理
3**重定向,需要进一步操作来完成请求
4**客户端错误,请求包含语法错误或者无法完成请求
5**服务器错误,服务器在处理请求的过程中发生了错误
1.2.6.5.1 成功相关2
状态码英文名称描述
200OK请求成功,一般用于GET和POST
201Created已创建,成功请求并创建了新的资源,通常用于POST和OUT
1.2.6.5.2 重定向相关3
状态码英文名称描述
301Moved Permanly永久移动,请求的资源永久移动到新的URL,返回的信息包括新的URL,浏览器会自动定向到新的URL,今后任何新请求都使用新的URL代替
302Found临时移动,与301类似,但是资源只是临时被移动,客户端会继续使用原有URL
304Not Modified未修改,所请求的资源未修改,服务器返回此状态码时,不会返回任何资源,客户端通常会缓存访问过的资源
1.2.6.5.3 客户端相关4
  • 客户端请求有非法内容或者语法错误,导致请求失败
状态码英文名称描述
400Bad Request1,语义有误当前请求无法被服务器理解
2,请求参数有误
401Unauthorized当前请求需要用户验证
403Forbidden服务器已经理解请求,但是拒绝执行
404Not Found服务器无法根据客户端的请求找到资源
408Request Timeout请求超时
1.2.6.5.4 服务端相关5
状态码英文名称描述
500Internal Server Error服务器内部错误
501Not Implemented服务器不支持该请求方法
502Service 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_rsaid_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 包名 --Snpm install 包名 --save 简写
npm install 包名 --save-dev安装的包只用于开发环境,出现在package.json的devDependencise属性中
npm install 包名 -Dnpm 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 文件路径 -omd转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