前后端数据交互
// TODO:重整
前后端数据交互
初始前后端通信
前后端通信方式什么?
前端和后端数据交互的过程<=>浏览器和服务器交互的过程
前端向后端发送数据:
1.登录功能
2.搜索功能
后端向前端发送数据:
页面上的图、文字等内容
前后端通信的过程与概念解释
前后端通信的过程
前后端通信是在请求-响应
中完成的概念解释
- 前端:
浏览器端
- 客户端:只要能和通信的就叫
客户端
- 后端:
服务器端
前后端的通信方式
- 使用浏览器访问网页
在浏览器地址栏输入网址,按下回车
- Html 的标签
浏览器在解析 Html 标签的时候,遇到一些特殊的标签( link
img
script
iframe
),会再次向服务器发送请求
还有一些标签(a
,from(表单)
),浏览器解析的时候,不会向服务器发送请求,但是用户可以使用他们向服务器发送请求
- Ajax Fetch
服务端职责
- 处理
HTTP
请求(req
,res
) - 定义路由,供前端
Ajax
访问 - 使用数据库,存储和查询数据
服务端处理数据:路由
::: tip 路由和 URL 的关系
GET /api/list 路由 ---> axios.get('api/list?a=1')
路由是规则,url 是具体的形式两者不同
:::
路由是服务端的入口规则,也是与前端的“约定”
路由主要包含:
- 定义
method
,如GET
,POST
等 - 定义
url
规则,如/api/list
和/api/create
- 定义输入
Request body
和输出Response body
格式
HTTP 协议
初识 HTTP
http
协议规定了客户端和服务端如何通讯
url
:后端接口的地址,即前端Ajax
请求时的地址method
:请求方法,如GET
POST
PUT
DELETE
等- 状态码:接口返回的状态,如
200
302
404
500
等 Request
:请求Request Body
:请求时发送给后端的数据Request Content-type
:发送数据的格式,如json
Response
:响应Response Body
:后端返回给前端的数据Response Content-type
:返回数据的格式,如json
- HTTP (
hypeText Transfer Protocol
:超文本传输协议)
HTML
:超文本标记语言,超文本:原先一个个单一的文本,通过超链接将其联系起来。由原先的单一的文本变成了可无限伸、扩展的超級文本、立体文本
HTML、JS、CSS、图片、字体、音频、视频等等文件,都是通过HTTP
在服务器和浏览器之间传输
每一次前后端通信,前端需要主动向后端发岀请求,后端接收到前端的请求后,可以给出响应
HTTP
是一个请求-响应协议
- HTTP 请求响应的过程
- 浏览器地址栏输入 URL 并回车
- 浏览器查找当前 URL 是否存在缓存,并比较缓存是否过期
- DNS 解析 URL 对应的 IP
- 根据 IP 建立 TCP 连接(三次握手)
- 发送 http 请求
- 服务器处理请求,浏览器接受 HTTP 响应
- 浏览器解析并渲染页面
- 关闭 TCP 连接(四次挥手)
http 报文
- HTTP 报文是什么
- 浏览器向服务器发送请求的时候,请求本身就是信息,叫
请求报文
- 服务器向浏览器发送响应时传输的信息,叫
响应报文
- HTTP 报文格式 // TODO:复查 2022.3.22
- 请求
- 请求头:起始行(黄色高亮部分)+首部(剩余部分为首部)
- 请求体
GET 请求没有请求体,数据是通过请求头携带
POST 请求,有请求体,数据通过请求体携带
- 响应
- 响应头:起始行+首部
- 响应体
HTTP 方法
- 常用的 HTTP 方法
浏览器发送请求时采用的方法。和响应无关
GET
POST
PUT
DELETE
用来定义对于资源采取什么样的操作的,有各自的语义
- HTTP 方法的语义
GET
获取数据 -POST
创建数据PUT
更新数据(修改个人信息 修改密码) -DELETE
删除数据
这些方法虽然有各自的语义,但是并不是强制性的
3.RESTful 接口设计
一种接口设计风格, 充分利用 HTTP 方法的语义
- 普通方法:
① 通过用户 ID 获取用户个人信息,使用 GET 方法https://www.xxx.com/api/http/getUser?id=1
② 注册新用户,使用 POST 方法https://www.xxx.com/api/http/addUser
③ 修改一个用户,使用 POST 方法https://www.xxx.com/api/http/modifuUser
③ 删除一个用户,使用 POST 方法 https://www.xxx.com/api/http/deleteUser
- RESTful 接口风格
只需要定义一个接口:https://www.xxx.com/api/http/User
分别通过四种语义的方法:GET(获取信息)、POST(注册用户)、PUT(修改信息)、DELETE(删除信息)
GET 和 POST 方法的对比
语义:
GET
:获取数据,POST
:创建数据发送数据
GET 通过地址在请求头中携带数据,能携带的数据和地址的长度有关,一般最多就几 K
POST 既可以通过地址在请求头中携带数据,也可以通过请求体携带数据,能携带的数据理论上是无限量的
携带少量数据,可以使用 GET 请求。大量的数据可以使用 POST 请求
缓存:Get 可以被缓存,post 不会被缓存
安全性:GET 和 POST 都不安全
HTTP 状态码
定义服务器对请求的处理结果,是服务器返回的
100-199
=>消息:代表请求已经被接受,需要继续处理
200-299
=>成功:200
300-399
=>重定向:301永久重定向
,除非用户手动清除缓存;302临时重定向
,不会缓存;304没有修改
,所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。
400-499
=>请求错误:404Not Found(没有找到)
500-599
=>服务器错误:500服务器内部错误,无法完成请求
ajax
Ajax 简介
Ajax
即“Asynchronous Javascript And XML
”(异步 JavaScript 和 XML),是指一种创建交互式、快速动态网页应用的网页开发技术,无需重新加载整个网页的情况下,能够更新部分网页的技术。
Ajax
中的异步:可以异步地向服务器发送请求,在等待响应的过程中,不会阻塞当前页面,浏览器可以做自己的事. 直到成功获取响应后,浏览器才开始处理响应数据。
XML
可扩展标记语言,是前后端数据通信时传输数据的一种格式
XML
现在已经不怎么用了,现在比较常用的时JSON
Ajax
其实就是浏览器与服务器之间的一种 异步通信方式
使用Ajax
可以在不重新加载整个页面的情况下, 对页面的某部分进行更新
Ajax 的基本用法
Ajax
想要实现浏览器与服务器之间的异步通信,需要依靠XMLHttpRequest
,它是一个构造函数
- 创建 xhr 对象
const xhr = new XMLHttpRequest()
- 监听事件,处理响应
当获取到响应后,会触发 xhr 对象的readystatechange
事件,可以在该事件中对响应进行处理
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return
//HTTP CODE
//获取响应后,响应的内容会自动填充xhr对象的属性
if ((xhr.status >= 200) & (xhr.status < 300) || xhr.status === 304) {
console.log('正常使用')
//数据
console.log(xhr.responseText)
}
}
readystatechange
事件监听readyState
这个状态的变化 一共有 5 个状态
- 0:未初始化,尚未调用
open()
- 1:启动,已经调用
open()
,但尚未调用send()
- 2:发送,已经调用
send()
,当尚未接收到响应 - 3:接收,已经接收到部分响应数据
- 4:完成,已经接收到全部响应数据,并且可以在浏览器中使用
- 准备发送请求
调用open()
并不会真正发送请求,而只是做好发送请求前的准备工作
xhr
.open
//'http方法',
//"地址url",true或false:是否为异步请求,一般肯定true
()
- 发送请求
调用send()
正式发送请求
send()
的参数是通过请求体携带的数据
xhr.send(null) //GET请求一般填null,因为GET不能通过请求体携带数据
eg:使用Ajax
来完成前后端通信
const url = 'https://www.imooc.com/api/http/search/suggest?words=js'
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.responseText)
}
}
xhr.open('get', url)
xhr.send(null)
GET 请求
- 携带数据
GET
请求不能通过请求体携带数据,但可以通过请求头携带, 在 url 对应的接口下添加名值对 - 数据编码
如果携带的数据时非英文字母的话,比如说汉字,就需要编码之后再发送给后端,不然会造成乱码问题
POST 请求
- 携带数据
POST
请求主要通过请求体携带数据,同时也可以通过请求头携带
const url = 'https://www.imooc.com/api/http/search/suggest?words=js'
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.responseText)
console.log(typeof xhr.responseText)
}
}
xhr.open('POST', url)
//如果想发送数据,直接写在 send()的参数位置,一般是字符串
// 不能直接传递对象,需要先将对象转换成字符串的形式
xhr.send('username=alex&age=18')
- 数据编码:如果携带的数据时非英文字母的话,比如说汉字,就需要编码之后再发送给后端,不然会造成乱码问题
JSON
初识 JSON
javascript object notation
,Ajax
发送和接受的一种数据格式为什么需要 JSON
JSON 有 3 种形式,每种形式的写法都和JS
中的数据类型很像,可以很轻松的和JS
中的数据类型互相转换
JSON 的三种形式
- 简单值形式
文件名:xxx.json
JSON 的简单值形式就对应着 JS 中的基础数据类型,数字,字符串,布尔值,null
- 对象形式
JSON
的对象形式就对应着JS
中的对象
{
"name": "张三",
"age": 18,
"hobby": ["足球", "乒乓球"]
}
- 数组形式
JSON
的数组形式就对应着 JS 中的数组
::: warning 注意事项
- JSON 中没有
underfined
值 - JSON 中的字符串必须使用双引号
- JSON 中是不能注释的
- JSON 中对象的属性名必须使用双引号,属性值如果是字符串也必须用双引号。 :::
JSON 的常用方法
JSON.parse()
可以将JSON
格式的字符串解析成 JS 中的对应值
一定要是合法的JSON
字符串,否则会报错JSON.stringify()
可以将JS
的基本数据类型,对象或者数组转换成JSON
格式的字符串
xhr.open('POST', url, true)
xhr.send(
JSON.stringify({
name: '张三',
hobby: ['足球', '乒乓球'],
})
)
- 使用 JSON.parse()和 JSON.stringify()封装 localStorage
const storage = window.localStorage
// 设置
const set = (key, value) => {
storage.setItem(key, JSON.stringify(value))
}
// 获取
const get = key => {
return JSON.parse(storage.getItem(key))
}
// 删除
const remove = key => {
storage.removeItem(key)
}
// 清空
const clear = () => {
storage.clear()
}
跨域
简介
向一个域发送请求,如果要请求的域和当前域是不同域,就叫跨域
不同域之间的请求,就是跨域请求
什么是不同域,什么是同域
https(协议):// www.imooc.com (域名) :443 (端口号) /course/list (路径)
- 协议 域名 端口号 任何一个不一样 就是不同域
- 与路径无关,路径不一样无所谓
跨域请求为什么会被阻止
- 阻止跨域请求,其实是浏览器本身的一种安全策略---
同源策略
- 其他客户端或者服务器不存在跨域被阻止的问题
跨域解决方案
CORS
跨域资源共享JSONP
- 优先使用
CORS
,如果浏览器不支持,使用JSONP
CORS 跨域资源共享
使用 CORS 跨域的过程
① 浏览器发送请求
② 后端在响应头中添加 Access-Control-Allow-Origin
头信息
③ 浏览器接收到响应
④ 如果是同域下的请求,浏览器不会额外做什么,这次前后端通信就圆满完成了
⑤ 如果是跨域请求,浏览器会从响应头中查找是否允许跨域访问
⑥ 如果允许跨域,通信圆满完成
⑦ 如果没找到或不包含想要跨域的域名,就丢弃响应结果
CORS
兼容性:IE10 及以上可以正常使用
JSONP
- 原理
script
标签跨域不会被浏览器阻止JSONP
主要就是利用SCRIPT
标签,加载跨域文件 - 使用
JSONP
实现跨域
服务器端准备好JSONP
接口
手动加载JSONP
标签或
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script type="text/javascript">
const handleResponse = data => console.log(data)
</script>
<script src="https://www.imooc.com/api/http/jsonp?callback=handleResponse"></script>
</body>
</html>
动态加载JSONP
接口
// 动态加载JSONP接口
const script = document.createElement('script')
script.src = 'https://www.imooc.com/api/http/jsonp?callback=handleResponse'
document.body.appendChild(script)
const handleResponse = data => {
console.log(data)
}
XHR 对象
XHR 的属性
responseType
和response
属性
responseText
只能在没有设置responseType
或者responseType=''
或responseType='text'
的时候才能使用response
可以替代responseText
,默认返回字符串,可以通过responseType
设置返回形式(如果设置为JSON
,浏览器默认调用JSON.parse()
解析成 JS 中的对应值,但服务器还是返回的是JSON
格式的字符串)
xhr.responseType = 'json'
timeout
属性:设置请求的超时时间(单位:ms)withCredentitals
属性
- 指定使用
Ajax
发送请求时是否携带Cookie
- 使用
Ajax
发送请求,默认情况下,同域时,会携带Cookie
,跨域时,不会 - 最终是否能成功跨域携带
Cookie
,还要看服务器同不同意
xhr.withCredentials = true
XHR 方法
abort()
:终止当前请求,一般配合 abort 事件一起使用setRequestHeader()
:可以设置请求头信息
// 请求头中的`Content-Type`字段用来告诉服务器,浏览器发送的数据是什么格式的。
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') // 对应的数据格式:'username=ased&password=asd'
xhr.setRequestHeader('Content-Type', 'application/json') // JSON格式的数据
XHR 的事件
load
事件:响应数据可用时触发 推荐使用onload
代替onreadystatechange
const url = 'https://www.imooc.com/api/http/search/suggest?words=js'
const xhr = new XMLHttpRequest()
xhr.addEventListener(
'load',
() => {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.response)
console.log(typeof xhr.response)
}
},
false
)
xhr.responseType = 'json'
xhr.open('GET', url, true)
xhr.send()
- error 事件
请求发生错误时触发
const url = 'https://www.imooc1.com/api/http/search/suggest?words=js'
const xhr = new XMLHttpRequest()
xhr.addEventListener(
'load',
() => {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.response)
console.log(typeof xhr.response)
}
},
false
)
xhr.addEventListener('error', () => {
console.log('访问出错拉!')
})
xhr.responseType = 'json'
xhr.open('GET', url, true)
xhr.send()
- abort 事件
调用 abort()终止请求时触发
const url = 'https://www.imooc.com/api/http/search/suggest?words=js'
const xhr = new XMLHttpRequest()
xhr.addEventListener(
'abort',
() => {
console.log('543629463')
},
false
)
xhr.addEventListener('error', () => {
console.log('访问出错拉!')
})
xhr.responseType = 'json'
xhr.open('GET', url, true)
xhr.send()
xhr.abort()
- timeout 事件
var xhr = new XMLHttpRequest()
xhr.responseType = 'json'
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.response)
}
}
xhr.open('GET', 'https://www.imooc.com/api/http/search/suggest?words=js')
xhr.timeout = 10
xhr.ontimeout = function (e) {
console.log('Timeout!!')
}
xhr.send()
FormData
使用 Ajax 提交表单(避免直接提交表单跳转)
FormData 可用于发送表单数据
<body>
<form id="login">
<input type="text" name="username" placeholder="用户名" />
<input type="password" name="password" placeholder="密码" />
<input type="submit" id="submit" value="提交" />
</form>
<script>
const login = document.getElementById('login')
const btn = document.getElementById('submit')
const url = 'https://www.imooc.com/api/http/search/suggest?words=js'
btn.addEventListener(
'click',
e => {
// 阻止表单跳转
e.preventDefault()
const xhr = new XMLHttpRequest()
xhr.addEventListener(
'load',
() => {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.response)
}
},
false
)
xhr.open('POST', url, true)
xhr.responseType = 'json'
const data = new FormData(login)
xhr.send(data)
},
false
)
</script>
</body>
FormData 的基本用法
// 通过 HTML 表单元素创建 FormData 对象
const fd = new FormData(表单元素)
xhr.send(fd)
// 通过 自身的append() 方法添加数据
const fd = new FormData(表单元素)
fd.append('age', 18)
fd.append('sex', 'male')
xhr.send(fd)
封装 Ajax
1、ajax
的原理需要掌握一下。即ajax
这门技术是使用XMLHttpRequest
这个对象实现的,该对象有一些方法和属性,比如open()
、send()
、responseType
......它们的含义是什么要知道。 2、ajax
的具体实现不需要自己手动封装。 3、实际开发中会使用现成的插件,我们只需要按照插件的文档使用即可
源代码:
axios
- 基于 Promise 的 HTTP 库
- axios 官方文档
Fetch
- 也是前后端通信的一种方式
- 是
Ajax
的一种替代方案,它是基于Promise
的 Ajax
的兼容性比Fetch
好