前后端通信
初识前后端通信
就是前端与后端数据交互的过程
HTML 的标签:
link/img/script 标签 这些都是向服务器端发出请求
还有一些标签 需要通过击点或填写发送请求
a/ form 标签
HTTP 协议
初识 HTTP
超文本传输协议
每一次前后端通信,前端需要主动向后端发出请求后,可以给出响应
HTTP 报文 __重要
报文是什么?
请求报文 和 响应报文
HTTP 报文的格式
请求:
请求头:起始行+首部
请求体
Get 请求,没有请求体,数据通过请求头携带
Post 请求,有请求体,数据通过请求体携带
响应
响应头:起始行+首部
响应体
HTTP 方法
常用的HTTP方法
浏览器发送请求时采用的方法,和响应无关
分别有 GET、POST、PUT、DELETE
HTTP方法的语义
GET 获取数据
->获取资源(文件)
POST 创建数据
->注册
PUT 更新数据
-> 修改个人信息,修改密码
DELETE 删除数据
-> 删除一条评论
- RESTFUL接口设计
充分利用HTTP方法的语义
GET 和 POST 方法的对比 __重要
语义
GET 获取
POST 创建
发送数据
GET 通过地址在请求头中携带数据
能携带的数据量和地址的长度有关,一般最多就几K
POST 即可以通过地址在请求头中携带数据,也可以通过请求体携带数据
携带量比较大
总结: 携带少量数据,可以使用GET请求,
大量的数据可以使用POST请求
缓存
GET 可以被缓存,
POST 不会被缓存,
安全性
POST 较 GET 稍安全
HTTP 状态码
状态码的语义
100-199 表示通知你,服务器已接收请继续
200-299 成功
200
300-399 重定向
304 无修改 即缓存
400-499 请求错误
500-599 服务器错误
本地存储
cookie
初识 Cookie
存储在用户本地,而不是存储在服务器上,是本地存储
一般会自动随浏览每次请求发送到服务器端
Cookie 有什么用
利用cookie 跟踪统计用户讯问该网站的习惯,比如什么时间访问,访问了哪些页面
Cookie 的基本用法
写入 Cookie
document.cookie = 'surname = zs';
document.cookie = 'age = 18';
读取 Cookie
同样使用document
console.log(document.cookie);
Cookie 的属性
Name 名称 Value 值
最重要的两个属性,创建Cookie时必须填写,其它属性可以使用默认值
Cookie 的名称或值如果包含非英文字母,则写入时需要使用 encodeURIComponent() 编辑 读取时用decodeURIComponent ()解码
名称要用英文, 值可以随便用中文,但必须编码
document.cookie = `username = ${encodeURIComponent('张三')}`;
- 失效 时间
对于失效的 Cookie, 会被浏览器清除
如果没有设置失效时间,这样的Cookie 称为会话 Cookie
它存在内存中,当会话结束,也就是浏览器关闭时,Cookie 消失
想长时间存在, 设置expires 或 Max-Age
expires 值为Date 类型 ,表示具体什么时间过期,
第二个属性设置时用 **;**号隔开
document.cookie = `username = alex; expires = ${new Date('2023-06-18 00:00:00')}`
max-age
值为数字,表示当前时间 + 多少秒后过期,单位是秒
如果数为0,则Cookie 会被删除
document.cookie = `username = alex; max-age = 5`
Domain 域
限定了 cookie
secure
https 模式下才能生效Cookie
Cookie 的封装
// 写入
const set = (name,value,{maxAage,domain,path,secure}={})=>{
let cookieText = `${encodeURIComponent(name)} = ${encodeURIComponent(value)}`;
if (typeof maxAage === 'number'){
cookieText += `; max-age = ${maxAage}`;
}
if(domain){
cookieText += `; domain = ${domain}`;
}
if(path){
cookieText += `; path = ${path}`;
}
if(secure){
cookieText += `; secure`;
}
document.cookie = cookieText;
};
// 通过 name 得到 Cookie
const get = name=>{
const cookies = document.cookie.split('; ');
for(const ltem of cookies){
const [cookieName,cookVlue] = ltem.split('=');
if(cookieName === name){
return decodeURIComponent(cookVlue)
}
}
return;
}
export {set,get};
需要注意的是每个域名下的 Cookie的设置数量是有限制的
4K
localStorage
初识 localStorage
只存储在本地,不会发送到服务器端
localStorage 的基本用法 __重要
setltem() 设置
localStorage.setItem('username','zs');
localStorage.setItem('age',18);
getltem() 访问
localStorage.getItem('username')
获取不存在的会返回 null
removeltem () 删除
localStorage.removeItem('age')
clear () 清除
小知识:
- 在form表单中,可以通过定义常量form的dom节点,然后打点调用 input 的name 来访问其内部的子表,并再打点调用用value 来获得它的值
localStorage.setItem('username',loginForm.username.value)
- form 元素 有一个submit () 方法,表示提交的意思
自动填充账户名
const logForm = document.getElementById('login');
const btn = document.getElementById('btn');
//根据名字 获取值
const username = localStorage.getItem('username')
if(username){
logForm.username.value = username;
}
btn.addEventListener('click',e=>{
//阻止默认的提交
e.preventDefault();
//设置localStorage
localStorage.setItem('username',logForm.username.value);
//然后提交
logForm.submit()
},false)
localStorage 的注意事项
存储期限
是持久化的本地存储,除非自己删除
sessionStorage
当会话结束的时候,数据就清空了
localStorage 健和值的类型
只能是字符串类型
Ajax
Ajax 基础
异步地向服务器发送请求
Ajax其实就是浏览器与服务器之间的一种异步通信方式
使用Ajax可以在不重新加载整个页面的情况下,对页面的某部分进行更新
Ajax 的基本用法__重要
XMLHttpRequest
Ajax 需要依靠XMLHttpRequest ,它是一个构造函数
我们需要实例化此构造函数,命名为xhr
它拥有默认的几个属性和方法
xhr.open() //准备
xhr.send() //发送
xhr.readyState // 状态值
xhr.status //HTTP状态码
xhr.responseText //获取到的文本类型的响应数据
xhr.response //响应数据
xhr.responseType //设置响应数据的类型
xhr.timeout //设置请求超时时间 配合timeout事件使用
xhr.withCredentials = true; // 跨域携带cookie
xhr.abort() //终止当前请求 配合abort事件使用
//事件
xhr.onreadystatechang //状态的变化
xhr.onload //响应数据可用时触发
xhr.ontimeout //请求超时时就会触发
xhr.error // 请求发生错误时触发
xhr.abort // 调用abort()终止请求时触发
Ajax 的使用步骤 - —重要
1.创建:
const xhr = new XMLHttpRequest();
2.监听事件,处理响应
当获取到响应后,会触发xhr对象的readystatechange
事件,可以在该事件中对响应进行处理
xhr.onreadystatechange=()=>{
//如果没有接收完数据,直接返回
if(xhr.readyState !== 4)return;
// 获取到响应后,响应的内容会自动填充xhr对象的属性
if((xhr.status >=200 & xhr.status <300)||(xhr.status === 304)){
console.log(xhr.reponseText);
}
}
readystatechange 事件监听 readyState 这个状态的变化
它的值从 0~4, 一共5个状态
状态4:表示数据已接收完成
3.准备发送请求:
调用open并不会真正发送请求,而只是做好发送请求前的准备工作
xhr.open('HTTP方法get/post','URL地址','true')
4.发送请求
调用sned()正式发送请求,并可以携带数据;
send()的参数是通过请求体携带的数据,所以如果open处用的是get 方法携带的数据,则send方法()为空即可。
xhr.send() //里面只能传字符串形式的数据
注意事项:
获取响应后,响应的内容会自动填充xhr对象的属性
不使用 this, 仍然使用xhr.
创建完xhr对象后就直接监听即可,用on兼容性要好
使用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);
console.log(typeof xhr.responseText);
} };
//准备
xhr.open('GET',url,true);
//发送
xhr.send(null);
GET 请求
1.携带数据
通过请求头来 携带,通过url 的?号后,用键值对的形式书写
例:单个请求:
多个请求: 用&来连接
words=js&username=alex
const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
2.数据编码
如果携带的数据是非英文字母的话,就需要编码
可以使用 encodeURIComponent() 编码
const url = `https://www.imooc.com/api/http/search/suggest?words=${encodeURIComponent('前端')}`;
POST 请求
携带数据
主要通过请求体来携带
同时也可以通过请求头来携带
如果想发送数据,直接写在send()的参数位置,一般是字符串形式
xhr.send(‘age=18&username=alex’);
也可以传对象形式,但需要JOSN编码
数据编码
同get
JSON
初识JSON
Ajax 发送和接收数据的一种格式
JSON 的3种形式__重要
1.简单值形式
对应着JS中的四种基本数据类型;
.json 中字符串必须用双引号
json中没有 undefined 值
json 中不能有注释
2.对象形式
对应着JS中的对象;
{
"name":"张三",
"age":18,
"hobby":["足球","蓝天"],
"family":{
"father":"张老大",
"mother":"椭球要"
}
}
注意:
对象的属性名必须用双引号,属性值如果是字符串也必须用双引号
只要涉及到字符串,就必须使用双引号
不支持 undefined
3.数组形式
对应着JS中的数组
[
{
"id":1,
"username":"张三",
"comment":"666"
},
{
"id":12,
"username":"李四",
"comment":"888"
}
]
只要涉及到字符串,就必须使用双引号
不支持 undefined
JSON 的常用方法
JSON.parse ()
可以将JSON格式的字符串解析成JS中的对应值
console.log(JSON.parse(xhr.responseText))
JSON.stringify()
可以把JS的基本数据类型、对象和数据转换成JSON格式的字符串
xhr.send(JSON.stringify({
name:'alex',
age:18
}))
使用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()
};
export {set,get,remove,clear}
跨域
什么是跨域
如果请求的域和当前域是不同域,就叫跨域
不同域之间的请求,就是跨域请求
什么是不同域,什么是同域
协议、域名、端口号,任何一个不一样,就是不同域
与路径无关,路径一不一样无所谓
跨域请求为什么会被阻止
阻止跨域请求,其实是浏览器本身的一种安全策略 -> 同源策略
跨域解决方案2个:
-
CORS 跨域共享 (优先使用)
Access-Control-Allow-Origin:* -
JSONP script
XHR 对象
----属性----
responseType 和 response 属性
设置响应数据的类型:默认就是文本形式的响应内容。
xhr.responseType = 'text'
xhr.responseType = 'json'
用这个属性设置json 的好处 是,浏览器会自动把json数据转化成js数据,省略了自已转,不再使用 JSON.parse()
接收响应数据:
xhr.response
timeout 属性
设置请求的超时时间(单位ms)
写在open之后
xhr.timeout = 10000;
如果超时,就是触发 timeout 事件。
withCreaentials 属性
指定使用Ajax 发送请求时是否携带Cookie
使用Ajax 发送请求,默认情况下,同域时,会携带Cookie;跨域时不会
跨域携带时可以设置:xhr.withCreaentials = true;
服务器端across也需要相应的设置,才会成功携带;
----方法----
1.abort ()
终止当前请求,一般配合abort事件一起使用
写在send之后
xhr.abort()
2.setRequestHeader ()
主要是POST格式下 可以设置请求头信息,写在发送之前,
请求头中的 Content-Type 字段用来告诉后端服务器,浏览器发送的数据是什么格式的
// 请求数据如果是字符串格式,就可以写上这个以告诉服务器,
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
// 请求数据如果是json格式,就可以写上这个以告诉服务器,
xhr.setRequestHeader('Content-Type','application/json')
发送JSON格式的,需要后端出具后端JSON接口
XHR的事件
load 事件
响应数据可用时触发; 优先使用 这个事件
xhr.onload = ()=>{
if((xhr.status >=200 && xhr.status <300)||xhr.status === 304){
console.log(xhr.response);
}
}
error 事件
请求发生错误时触发;
xhr.addEventListener('error',()=>{
console.log('error');
},false)
abort 事件
调用abort()终止请求时触发,配合abort()方法使用
xhr.addEventListener('abort',()=>{
console.log('abort');
},false)
timeout 事件
请求超时时就会触发;
xhr.addEventListener('timeout',()=>{
console.log('timeout');
},false)
------Ajax 进阶---------
FormData
可用于发送表单数据;亦可独立于表单,用于发送键值对数据。
使用Ajax提交表单
const login = document.getElementById('login');
const btn = document.getElementById('btn');
const { username, password } = login;
const url = `https://www.imooc.com/api/http/search/suggest?words=${encodeURIComponent('前端')}`;
btn.addEventListener('click', e => {
// 阻止自动提交
e.preventDefault();
// 数据验证
// 发送Ajax请求
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);
// FormData 是构造函数,直接把form表单元素传入即可;
const data = new FormData(login);
// 发送data
xhr.send(data)
}, false)
FormData的基本用法
通过HTML表单元素创建 FormData对象
const data = new FormData(表单元素);
xhr.send(data);
如果没有表单,还可以通过append() 方法单独添加数据
data.append('age',18);
xhr.send(data);
封装Ajax
使用 Promise 改造封装好的 Ajax
搜索提示
二级菜单
多个Ajax请求的并发执行
axios 第三方库
axios
是一个第三方 Ajax 库
官方文档:
http://www.axios-js.com/zh-cn/docs/
基本用法
<script src="https://unpkg.com/axios@1.4.0/dist/axios.min.js"></script>
<script>
const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
axios(url,{
method:'post',
//请求时的头信息
Headers:{
'Content-Type':'application/x-www-form-urlencoded'
},
//通过请求头携带的数据
params:{
username:'alex'
},
//通过请求体携带的数据(需要与传入规定格式保持一致)
data:'age=18&sex=male',
// timeout:10
}).then(
response=>{
console.log(response);
}
).catch(err=>{
console.log(err);
})
同样也有get方法
axios.get(url,{
params:{
username:'alex'
}
}).then(response=>{
console.log(response);
})
同样也有post方法
post不需要设置请求内容的格式
axios.post(url,{
data:{
usernam:'slfkjw'
}
}).then(response=>{
console.log(response);
})
Fetch
Fetch 是什么
Fetch 也是前后端通信的一种方式
Fetch 是 Ajax 的一种替代 方案,它是基于 promise 的
基本用法
fetch(url).then(response=>{
if(response.ok){
//读取json内容且自动转化js格式 并 返回出去
return response.json()
}else{
throw new Error(`HTTP CODE ERROR ${response.status}`)
}
}).then(data=>{
console.log(data);
})
.catch(err=>{
console.log(err);
})
数据在body 里,但只能读取一次
fetch 有第二个参数 是一个对象,用来配置fetch,不写则用默认值
fetch(url,{
method:'post',
body:'username=alex',
headers:{
'Content-Type':'appsflkjslfkj'
}
// 跨域资源共享
mode:'cors',
credentials:'include'