Ajax 是什么:
- Ajax 是 Asynchronus JavaScript and XML(异步 JavaScript 和 XML)的简写
- Ajax 其实就是浏览器与服务器之间的一种异步通信方式
- Ajax 中的异步:可以异步的向服务器发送请求,在等待响应的过程中,不会阻塞当前页面,浏览器可以做自己的事情;直到成功获取响应后,浏览器才开始处理响应数据
- XML(可扩展标记语言)是前后端数据通信时的一种数据传输格式(现在主流时 JSON)
XMLHttpRequest:
- Ajax 想要实现浏览器与服务器之间的异步通信,需要依靠 XMLHttpRequest 创建一个对象,XMLHttpRequest 是一个构造函数
readyState 的值:
- xhr.readyState 这个状态的变化值从 0~4 表示 5 种状态
- 0:请求还未初始化。尚未调用 open()方法
- 1:启动(请求已建立)。已经调用 open()方法,但未调用 send() 方法
- 2:请求已发送。已经调用 send() 方法,但未接收到响应
- 3:接收。开始接收响应数据
- 4:接收完成。已经全部接收完响应数据,可以在浏览器中使用了
status 的值:
- 1xx:收到请求
100:客户必须继续发送请求
101:客户要求服务器根据请求转换HTTP协议版本
- 2xx:表示成功处理请求,如:200
200:成功处理请求
201:提示知道新文件的URL
202:接受和处理、但处理未完成
203:返回信息不确定或不完整
204:请求收到,但返回信息为空
205:服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206:服务器已经完成了部分用户的GET请求
- 3xx:需要重定向,浏览器直接跳转
300:请求的资源可在多处得到
301:永远重定向到该资源
302:临时重定向到该资源
303:建议客户访问其他URL或访问方式
304:资源未改变,如果访问的资源没有改变,服务器返回304,浏览器使用缓存的资源
305——请求的资源必须从服务器指定的地址得到
306——前一版本HTTP中使用的代码,现行版本中不再使用
307——申明请求的资源临时性删除
- 4xx:客户端请求错误
400:错误请求,如语法错误
401:请求授权失败
402:保留有效ChargeTo头响应
403:客户端没有权限
404:请求地址错误或者服务的没有对应接口
- 5xx:服务端错误
500:服务器产生内部错误
501:服务器不支持请求的函数
Ajax 的使用步骤:
- 创建 XMLHttpRequest 的对象
let xhr = new XMLHttpRequest();
// 一般使用下面这种方式创建
let request;
if (window.XMLHttpRequest) {
// 这种方式是对于使用这几种浏览器的情况
// IE7+,Firefox,Chrome,Opera,Safari ...
request = new XMLHttpRequest();
} else {
// 这种方式是针对低版本浏览器:IE6,IE5
request = new ActiveObject("Microsoft.XMLHTTP");
}
// method 是 HTTP 请求方法:GET、POST、PUT、DELETE
// URL 地址:
// async 是否使用异步:true 或者 false
xhr.open(method, url, async);
// 当获取到响应后,会触发 xhr 对象的 readystatechange 事件,
// 可以在该事件中对响应进行处理
xhr.onreadystatechange = function() {
// readyState 这个状态的变化值从 0~4 表示 5 种状态
// 0:请求还未初始化。尚未调用 open()方法
// 1:启动(请求已建立)。已经调用 open()方法,但未调用 send() 方法
// 2:请求已发送。已经调用 send() 方法,但未接收到响应
// 3:接收。开始接收响应数据
// 4:接收完成。已经全部接收完响应数据,可以在浏览器中使用了
// status == 200 表示请求成功
if (xhr.readyState == 4 && xhr.status == 200) {
//将返回结果以文本(字符串)形式输出
document.write(xhr.responseText);
//将返回结果以XML形式输出
//docunment.write(xhr.responseXML);
// or lists = xhr.responseText
}
}
// send() 的参数是通过请求体携带的数据
// 如果是 GET 请求,括号里填 null 或者不填
xhr.send();
携带数据:
- GET 请求不能通过请求体携带数据,但可以通过请求头携带
- 在请求头的 url 后加“?属性=值”的方式添加数据
- 多个“属性=值”之间用“&”分隔
数据编码:
- 如果携带的数据是非英文字母的话,比如汉字,就需要编码后再发送给后端,不然会造成乱码问题
- 可以使用 encodeURIComponent() 编码
- 示例:url = http://localhost:8080/test?username = ${encodeURIComponent("名字") &age=18}
携带数据:
- 如果想发送数据,直接将参数写在 send() 方法括号里,一般是字符串
- 不能直接传递对象,需要先将对象转换成字符串的形式
数据编码:
- 可以使用 encodeURIComponent() 编码
- 示例:xhr.send(username=${encodeURIComponent("名字")} & age=18
);
if (xhr.readyState == 4 && xhr.status == 200) {
//将返回结果以文本(字符串)形式输出
document.write(xhr.responseText);
//将返回结果以XML形式输出
//docunment.write(xhr.responseXML);
}
responseType 和 response 属性:
- 上面 Ajax 响应中的 responseText 是文本形式的响应内容(或字符串形式)
- 当上面的 responseText 变为 response 时,可以在 xhr.open() 方法后面通过 xhr.responseType 设置具体的响应类型
- IE6~9不支持,IE10 才开始支持
xhr.open(method,url,async);
// 默认是空字符串
// xhr.responseType = '';
// 当设置为‘text’或空字符串时等效于上面设置的 responseText
xhr.responseType = 'text';
// 响应将以 JSON 形式输出
xhr.responseType = 'json';
timeout 属性:
- 用来设置请求的超时时间(单位:ms)
- 当上面的 responseText 变为 response 时,可以在 xhr.open() 方法后面通过 xhr.timeout 设置响应超时时间
- 当超时后会自动触发 timeout() 事件
- IE6~7不支持,IE8 才开始支持
xhr.open(method,url,async);
// 设置响应超时时间
xhr.timeout = 10000;
withCredentials 属性:
- 指定使用 Ajax 发送请求时是否携带 Cookie
- 使用 Ajax 发送请求,默认情况下,同域时,会携带 Cookie;跨域时,不会
- 同样的,当上面的 responseText 变为 response 时,可以在 xhr.open() 方法后面通过 xhr.withCredentials 设置是否携带 Cookie
- 最终能否成功跨域携带 Cookie,还要看服务器是否同意,若服务器同意,设置 Access-Control-Allow-Origin 时不能使用通配符 *,必须指定具体域名
- IE6~9不支持,IE10 才开始支持
xhr.open(method,url,async);
// 设置是否携带 Cookie true or false
xhr.withCredentials = true;
abort() 方法:
- abort() 方法用于终止当前请求
- 一般配合 abort 同名事件一起使用
- 该方法在 xhr.send() 方法后面调用
xhr.send();
// 设置终止当前请求
xhr.abort();
setRequestHeader() 方法:
- setRequestHeader() 方法用于设置请求头信息
- 该方法在 xhr.open() 方法后面调用
// 此方法针对 POST 请求
xhr.open('POST', url, true);
// 设置请求头信息
// 请求头中的 Content-Type 字段用来告诉服务器,浏览器发送什么格式的数据
xhr.setRequestHeader(‘Content-Type’, 'application/x-www-form-urlencoded');
// application/x-www-form-urlencoded 对应如下 表单 数据格式
xhr.send('username = alex&age=18');
// application/json 对应如下 json 数据格式
xhr.send(
JSON.stringify({
username = alex,
age=18
})
);
load 事件:
- 响应数据可用时触发
- 可用 onload 事件替换 onreadystatechange 事件
- IE6~8 不支持,IE9 及以上版本才支持 onload 事件
// 响应数据可用时 readyState 已经等于4
// xhr.onload = function() {
// if (xhr.readyState == 4 && xhr.status == 200) {
//将返回结果以文本(字符串)形式输出
// document.write(xhr.responseText);
//将返回结果以XML形式输出
//docunment.write(xhr.responseXML);
// }
// }
// load 事件配上 addEventListener
xhr.addEventListener('load', ()=>{
if (xhr.readyState == 4 && xhr.status == 200) {
//将返回结果以文本(字符串)形式输出
document.write(xhr.responseText);
//将返回结果以XML形式输出
//docunment.write(xhr.responseXML);
}
}, false);
error 事件:
- 请求发生错误时触发(是请求时错误,要与响应时错误区分开)
- IE10 及以上版本才支持
// load 事件配上 addEventListener
xhr.addEventListener('load', ()=>{
if (xhr.readyState == 4 && xhr.status == 200) {
//将返回结果以文本(字符串)形式输出
document.write(xhr.responseText);
//将返回结果以XML形式输出
//docunment.write(xhr.responseXML);
}
}, false);
xhr.addEventListener('error', ()=>{
console.log('error');
});
abort 事件:
- 调用 abort() 方法终止请求时触发
- IE10 及以上版本才支持
// load 事件配上 addEventListener
xhr.addEventListener('load', ()=>{
if (xhr.readyState == 4 && xhr.status == 200) {
//将返回结果以文本(字符串)形式输出
document.write(xhr.responseText);
//将返回结果以XML形式输出
//docunment.write(xhr.responseXML);
}
}, false);
xhr.addEventListener('abort', ()=>{
console.log('触发事件后想执行的逻辑');
});
timeout 事件:
- 请求超时后触发
- IE8 及以上版本才支持
// load 事件配上 addEventListener
xhr.addEventListener('load', ()=>{
if (xhr.readyState == 4 && xhr.status == 200) {
//将返回结果以文本(字符串)形式输出
document.write(xhr.responseText);
//将返回结果以XML形式输出
//docunment.write(xhr.responseXML);
}
}, false);
xhr.addEventListener('timeout', ()=>{
console.log('触发事件后想执行的逻辑');
});
// 表单
<form id="login" action="" method="POST">
......
<input id="submit" type="submit" value="登陆" />
</form>
// 解构获取表单的参数和值
const {username, password} = login;
const btn = document.getElementById('submit');
// 点击提交触发事件
btn.addEventListener('click', e =>{
// 阻止表单自动提交
e.preventDefault();
// 表单数据验证
// 发送 Ajax 请求
let xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveObject('Mircosoft.XMLHTTP');
}
xhr.onreadystatechange =function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.response);
}
};
// 准备发送
xhr.open("POST", url, true);
// 组装数据
let data = `username=${username.value}&password=${password.value}`;
// 设置发送格式
xhr.setRequestHeader(‘Content-Type’, 'application/x-www-form-urlencoded');
// 发送
xhr.send(data);
},false);
FormData 的基本用法:
- 通过 HTML 表单元素创建 FromData 对象,然后直接将表单元素(login)传过去
- 也可以使用 append() 方法追加数据。例:data.append(“age”, 18);
- 使用 formData 的作用就是替换自己组装数据的过程,并且不用自己设置请求头的数据发送格式
// 表单
<form id="login" action="" method="POST">
......
<input id="submit" type="submit" value="登陆" />
</form>
// 解构获取表单的参数和值
const {username, password} = login;
const btn = document.getElementById('submit');
// 点击提交触发事件
btn.addEventListener('click', e =>{
// 阻止表单自动提交
e.preventDefault();
// 表单数据验证
// 发送 Ajax 请求
let xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveObject('Mircosoft.XMLHTTP');
}
xhr.onreadystatechange =function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.response);
}
};
// 准备发送
xhr.open("POST", url, true);
// 组装数据
const data = new FormData(login);
// 发送
xhr.send(data);
},false);
Fetch 是什么:
- Fetch 也是前后端通信的一种方式
- Fetch 是 Ajax(XMLHttpRequest)的一种替代方案,它是基于 Promise 的
Fetch 的基本用法:
axios 是什么:
- 第三方的 Ajax 库,是基于 Promise
- axios 的中文官方文档:http://www.axios-js.com/zh-cn/docs
axios 请求方法主要有:get、post、put、patch、delete
- get 方法主要用于获取数据
- post 方法主要用于提交数据(表单提交或文件上传)
- put 方法主要用于更新数据(将所有数据推送到后端)
- patch 方法也用于更新数据(只将修改的数据推送到后端)
- delete 方法主要用于删除数据
// 请求到URL为:http://localhost:8080/hello?id=1
// 第一种形式
axios.get('/hello', {
params: {
id: 1
}
}).then((res) => {
console.log(res)
})
// 第二种形式
axios({
method: 'get',
url: '/hello',
params: {
id: 1
}
}).then((res) => {
console.log(res)
})
// 请求到URL为:http://localhost:8080/post
// json 形式数据
let data = {
id: 2
};
// 第一种形式:别名形式
axios.post('/post', data).then((res) => {
console.log(res)
})
// 第二种形式
axios({
method: 'post',
url: '/post',
data: data
}).then((res) => {
console.log(res)
})
// form-data 形式数据
let formData = new FormData()
for(let key in data) {
formData.append(key, data[key])
}
axios.post('post', formData).then((res) => {
console.log(res)
})
let data = {
id: 2
};
// put:别名形式
// 请求到URL为:http://localhost:8080/put
axios.put('/put', data).then((res) => {
console.log(res)
})
// patch:别名形式
// 请求到URL为:http://localhost:8080/patch
axios.patch('/patch', data).then((res) => {
console.log(res)
})
// 第一种形式:别名形式
// 如果需要在请求URL上加参数
// 请求到URL为:http://localhost:8080/delete?id=1
axios.delete('/delete', {
params: {
id: 1
}
}).then((res) => {
console.log(res)
})
// 不需要在请求URL上加参数
// 请求到URL为:http://localhost:8080/delete
axios.delete('/delete', {
data: {
id: 1
}
}).then((res) => {
console.log(res)
})
// 第二种形式:不使用别名
// 如果需要在请求URL上加参数
// 请求到URL为:http://localhost:8080/delete?id=1
axios({
method: 'delete',
url: '/delete',
params: {
id: 1
}
}).then((res) => {
console.log(res)
})
// 不需要在请求URL上加参数
// 请求到URL为:http://localhost:8080/delete
axios({
method: 'delete',
url: '/delete',
data: {
id: 1
}
}).then((res) => {
console.log(res)
})
axios.all([
axios.get('hello'),
axios.get('world')
]).then(
axios.spread((helloRes, worldRes) => {
// 这里面可以进行多个请求数据的处理
console.log(helloRes, worldRes)
})
)
import axios from 'axios'
const instance = axios.create({
baseURL: 'http://localhost:8080',
timeout: 1000
});
instance.get('/hello').then((response) => {
console.log(response)
})
headers: {
token: '', // 一般用来识别登陆人的信息
Content-Type: application/json // 请求数据格式
}
axios 全局配置:
axios.defaults.baseURL = 'http://localhost:8080'
axios.defaults.timeout = 1000
axios 实例配置:
let instance = axios.create()
instance.defaults.baseURL = 'http://localhost:8080'
instance.defaults.timeout = 1000
axios 请求配置:
let instance = axios.create()
instance.get(url, {
baseURL = 'http://localhost:8080',
timeout = 1000
})
// 请求拦截器
axios.interceptors.request.use(
(config) => {
// 在请求前可以做一些事,例如:修改配置,修改内容
console.log(config)
// 完成操作后一定要将 config 返回
return config
}, (err) => {
// 在请求错误的时候可以做一些事
// 返回的是一个 Promise对象
return Promise.reject(err)
})
// 响应拦截器
axios.interceptors.response.use(
(res) => {
// 请求成功后对响应数据做处理
console.log(res)
// 完成操作后一定要将 response 返回
// 返回的数据会到 axios.get或post().then(res => {}) 的 then方法里
return res
}, (err) => {
// 在响应错误的时候可以做一些事
// 返回的是一个 Promise对象
// 返回的数据会到 axios.get或post().then(res => {}).catch(err => {}) 的 then方法的第二个回调函数或者 catch 方法里
return Promise.reject(err)
})
JSON 是什么:
- JSON 全称是(JavaScript Object Notation)JavaScript的对象表示法
- JSON 是发送和接收数据的一种格式
为什么需要 JSON:
- JSON 有3种形式,每种形式和写法都和 JS 中的数据类型很像,可以很轻松的和 JS 中的数据类型互相转换
简单值形式:
- JSON 的简单值形式对应着 JS 中的基础数据类型
- 简单值形式有:数字、字符串、布尔值、null
// JSON 文件以 .json 结尾
{
12,
"这是字符串",
true,
null
}
注意事项:
- JSON 中没有 undefined 值
- JSON 中的字符串必须使用双引号
- JSON 文件中不能有注释
对象形式:
- JSON 中对象的属性名必须用双引号,属性值如果是字符串也必须用双引号
- JSON 中只要涉及字符串的地方一定要加双引号
- 不支持 undefined
- JSON 对象形式里面可以嵌套数组、对象、JS 基本数据类型等
// JSON 文件以 .json 结尾
{
"username" : "zhangsan",
"age" : 18,
"hobby" : ["看书","玩游戏","踢足球"],
“family” : {
"father" : "张爸",
"mother" : "张妈"
}
}
数组形式:
- JSON 数组形式里面也可以嵌套数组、对象、JS 基本数据类型
- 不支持 undefined
// JSON 文件以 .json 结尾
[
1,
"我是字符串",
["嵌套数组",2,"字符串",null],
{
"username" : "zhangsan",
"age" : 18
}
]
JSON.parse():
- 将JSON 格式的字符串转解析为 JS 对应的数据类型
JSON.stringify():
- 是将 JS 对应的数据类型转为对应的 JSON 格式的数据
使用 JSON.parse() 和 JSON.stringify() 封装 localStorage:
// js/storage.js
const storage = window.localStorage;
// 改为 sessionStorage 的方法同理
// const session = window.sessionStorage;
// 设置值
const set = (key, value) =>{
storage.setItem(key, JSON.stringify(value));
};
// 获取值
const get = key => {
return storage.getItem(key);
};
// 移除
const remove = () => {
storage.removeitem(key);
};
// 清空
const clear = () => {
storage.clear();
};
// 向外暴露函数
export {set, get, remove, clear};
// 在 HTML 中引入
<script type = "module">
import {get, set, remove, clear} from 'js/storage.js';
// 示例
set('userInfo',{
name: '张三',
age: 18
});
</script>
跨域是什么:
- 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
- 不同域之间的请求就是跨域请求
跨域请求为什么会被阻止:
- 阻止跨域请求的原因是浏览器本身的一种策略----同源策略
- 其它客户端或者服务器不存在跨域被阻止的问题,跨域只存在浏览器
跨域的解决方案:
- CORS 跨域资源共享
- JSONP
- 优先使用 CORS 跨域资源共享,如果浏览器不支持 CORS 的话,在使用 JSONP
URI 和 URL的区别:
- URI 是 Uniform Resource Identifier,统一资源标识符,用来唯一的标识一个资源。
- URL是 Uniform Resource Locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源。
- 简单区别就是 URL 比 URI 包含信息更多
CORS 是什么:
- CORS 是 跨域资源共享
- CORS 是由后端采取的措施
- 后端在响应中设置 Access-Control-Allow-Origin: * 表明允许所有的域名来跨域请求它,* 是通配符,表示没有任何限制
- 设置只允许指定域名的跨域请求,只要在 Access-Control-Allow-Origin: 后设置指定的域名即可。例如:Access-Control-Allow-Origin: http://127.0.0.1:8080
使用 CORS 跨域的过程:
- 浏览器向服务器端发送请求
- 如果服务器允许跨域,则后端服务需要在响应头中添加 Access-Control-Allow-Origin 头信息
- 浏览器接收到响应
- 如果是同域的请求,浏览器不会额外做什么,本次前后端通信完成
- 如果是跨域请求,浏览器会从响应头中查找是否允许跨域访问
- 如果是允许跨域,则通信完成
- 如果没找到或不包含想要跨域的域名,就丢弃响应的结果
CORS 的兼容性:
- IE10 及以上版本的浏览器可以正常使用 CORS
- 老版本识别不了响应头中的 Access-Control-Allow-Origin 字段
- 关于兼容性,可以参考该网站:https://caniuse.com/
JSONP 的原理:
- script 标签跨域不会被浏览器阻止
- JSONP 主要就是利用 script 标签加载跨域文件
使用 JSONP 实现跨域:
- 服务器端准备好 JSONP 接口。例如:https://www.test.com/jsonp?callback=response
- 手动使用 script 标签加载 JSONP 接口,
- 或者动态加载 JSONP 接口
const script = document.createElement('script');
script.src = 'https://www.test.com/jsonp?callback=response';
document.body.appendChild(script);