Ajax学习总结
什么是Ajax
Ajax是浏览器种的技术:用来实现客户端网页请求服务器的数据
英文全称是Asynchronous Javascript And XML,简称 Ajax。
有数据的地方就有Ajax.
请求方式
基本用法
axios专注于数据请求的库
中文官网地址:www.axios-http.cn/
基本语法
axios({
method: '请求的类型',
url: '请求的URL地址'
}).then((result) => {
// then 用来指定请求成功之后的回调函数
// 形参中的 result 是请求成功之后的结果
})
get
向服务器获取数据
-
可以直接在url上拼接参数
url: 'http://www.itcbc.com:3006/api/addbook?username=111&password=222' -
使用axios方法通过params对象进行传递
<!-- 1 引入axios --> <script src="./lib/axios.js"></script> <script> axios({ method: 'get', url: 'http://www.itcbc.com:3006/api/getbooks', // 请求的参数 同时指定多个参数 (我想要买手机 颜色是蓝色 并且 内存是 256G ) // 5913 Web开发实战 params: { // 0 条数据 多个参数的含义是 && 两个条件都要满足 不是 || 或者 // id === 5913 && 书名 === 万少 // 梦想 : 我想要找 一个对象 年薪1个亿 并且 70岁以上 id: 5913, bookname: '万少', }, }).then((result) => { console.log(result); const arr = result.data.data; render(arr); }); -
浏览器的地址访问接口,也是一种get请求
axios({
method: 'get',
url: 'http://www.itcbc.com:3006/api/getbooks' + query,
// params:{},
}).then((result) => {
console.log(result);
const arr = result.data.data;
render(arr);
});
}
post
传入参数 data
方式
-
字符串拼接
axios({ method: 'post', url: 'http://www.itcbc.com:3006/api/addbook', data:"bookname=从入门到出去123&author=我自己&publisher=黑马出版社&appkey=wanshao1234", }).then((result) => { console.log(result); }); -
data对象
axios({ method: 'post', url: 'http://www.itcbc.com:3006/api/addbook', data: { bookname: '从入门到精通', author: '我自己', publisher: '黑马出版社', appkey: 'wanshao1234', }, }).then((result) => { console.log(result); }); -
formdate(可以快速获取表单提交数据,也可以作为对象传入)
<form> <input type="text" name="username" value="123"> <input type="text" name="password" value="456"> </form> <script> const data = new FormData(document.querySelector("form")); const usp = new URLSearchParams(data); console.log(usp.toString()); </script>
<button>点击按钮-加载数据</button>
<script src="./lib/axios.js"></script>
<script>
const button = document.querySelector("button");
button.addEventListener("click",function() {
axios({
method:'post',
url:'http://www.itcbc.com:3006/api/addbook',
data:{
// id:"6666",
bookname:'Java入门到入土',
author:'巫斌斌',
publisher:'503出版社',
},
}).then((result)=>{
console.log(result);
});
});
</script>
delete
传入参数params
axios({
method:'delete',
url:'http://www.itcbc.com:3006/api/delbook',
params:{id},
}).then((result)=>{
console.log(result);
getData();
});
put
传入参数data
axios({
method: 'put',
url: 'http://www.itcbc.com:3006/api/updatebook',
data,
}).then(result => {
booknameValue.value = "";
authorValue.value = "";
publisherValue.value = "";
getData();
// console.log(result);
alert("修改成功");
})
confirm弹出确认框
<button>删除</button>
<script>
document.querySelector("button").addEventListener("click",function() {
if (confirm("您确定删除么?么么哒")) {
console.log("执行删除函数");
}else{
console.log("取消删除");
}
});
</script>
接口文档
接口
使用 Ajax 请求数据时,被请求的 URL 地址,就叫做数据接口(简称:接口或 API 接口)。
同时,每个接口必须有对应的请求方式。例如:
www.itcbc.com:3006/api/getbook… 获取图书列表的接口(GET 请求) http://www. itcbc.com:3006/api/addbook 添加图书的接口(POST 请求)
文档
接口文档就是接口的使用说明书,它是我们调用接口的依据。
格式
appkey身份认证
服务器存储的图书,分为通用数据和个人数据。
- 默认获取、添加、删除、修改的都是通用数据。
- 在获取、添加、删除、修改时,如果带appkey参数,则表示使用个人数据。
axios({
method: 'get',
url: 'http://www.itcbc.com:3006/api/getbooks',
params: {
appkey: 'wanshao1234',
}
network面板
面板介绍
常用设置
隐藏时间轴
禁用浏览器缓存
模拟网络(网速)
- No throttling -- 不限速
- Fast 3G -- 模拟快速3G网络
- Slow 3G – 模拟慢速3G网络
显示请求方式
*查看请求状态
*查看请求方式和完整URL
*查看传输到服务器的数据
*查看服务器响应结果
form表单
表单三个属性
表单提交数据
在
标签上,通过 action 属性指定提交的 URL 地址,通过 method 属性指定提交的方式为 POST,并通过 enctype 属性指定数据的编码方式为 application/x-www-form-urlencoded:注意:由于 enctype 的默认值就是 application/x-www-form-urlencoded,因此上述的 enctype 可以被省略!
<body>
<!--
旧方式 提交数据 form标签的方式 提交
1 肯定会出现 刷新页面 调整页面的情况 (体验! 很糟糕)
2 输入框没name属性 没有把数据 提交给到后端
新的方式 ajax
1 异步 网络请求 (异步 同时执行多个事情 - 你一边正在使用网页功能而且数据提交 同时进行(整个网页 ))
2 规范 只要写到input标签想要数据提交 习惯的加上 name属性
如果使用ajax的技术来提交数据 是完全不给标签添加name属性
3 习惯下来 form input标签name 都一直在使用
-->
<form action="http://www.itcbc.com:3006/api/getbooks" method="get">
<div>
<label for="">用户名</label>
<input type="text" name="username">
</div>
<div>
<label for="">密码</label>
<input type="text" name="password">
</div>
<div>
<label for="">随便的测试</label>
<input type="text">
</div>
<!-- <button type="submit">提交</button> -->
<button >提交</button>
</form>
快速获取表单数据
1.jQuery 的 serialize() 函数
jQuery 的 serialize() 函数能够一次性获取到表单中采集的数据,它的语法格式如下:
$('表单元素的选择器').serialize();
<body>
<form>
<input type="text" name="username" />
<input type="text" name="password" />
<input type="text" />
<button type="button">获取表单数据</button>
</form>
<script src="./lib/jquery.js"></script>
<script>
// 序列化
// 把对象或者数组 转成 字符串格式 过程 序列化 JSON.stringify();
// 把字符串格式 转成 对象或者数组 反序列化 JSON.parse()
const button = document.querySelector('button');
// 假设我想要使用 快速获取表单数据 序列化 功能
// 1 直接用jq的 serialize
// 2 es6 新的对象 用这些新的对象 构造自己的序列化 方法 - 没有演示
// 3 传统- 自己写代码 获取每一个input标签的 自己写代码进行字符串拼接 没有演示
// 讲解js基础 对象 数组 字符串 转来转去
button.addEventListener('click', function () {
// 使用jq的方法 获取表单的数据 (字符串)
// username=11&password=22 get请求 两种传递参数的方式
// 1 params对象
// 2 在url上拼接字符串的形式 http:/api?username=11&password=22
// const data = $("form").serialize();
const data = myfunc('form'); // 不要这么做 人品坏
console.log(data);
});
// function $() {
// console.log(1);
// }
// $();
function myfunc(query) {
return $(query).serialize();
}
</script>
注意点
-
必须为每个表单域添加 name 属性!
不然获取到的只有name属性的值,没有name属性的值获取不到
-
该方法是jQuery封装的,使用时必须引入jQuery
-
使用该方法得到的结果是一个查询字符串结构:name=value&name=value
-
该方法 能够 获取 隐藏域的值
-
该方法不能得到禁用状态的值
-
该方法不能得到文件域中的文件信息,所以不能完成文件上传
2.FormData
<form>
<input type="text" name="username">
<input type="text" name="password">
<input type="text" name="garden">
<button type="button">提交</button>
</form>
<script>
const button = document.querySelector("button");
button.addEventListener("click",function() {
const data = getForm("form");
console.log(data);
})
function getForm(query) {
//快速获取from表单中带有name属性的值,并传入到FormData中
const form = new FormData(document.querySelector(query));
//创建把数据转成get参数格式的对象
// URLSearchParams URL search params
const usp = new URLSearchParams(form);
/* form.forEach((value,key)=>{
//value = username表单的值
//key = username;
usp.append(key,value);
//usp.append("username",username的值);
//usp.append("password",password的值);
}) */
const data = usp.toString();
return data;
}
</script>
axios简写
<script src="./lib/axios.js"></script>
<script>
// axios.get();
// axios.post();
// axios.delete();
// axios.put();
// axios.get(url); 直接在地址后面拼接参数?......
// axios.get("http://www.itcbc.com:3006/api/getbooks?appkey=wanshao1234").then(result=>{console.log(result);})
// axios.get(url,参数);地址后面有个对象{}里面有参数params{参数}
// axios
// .get("http://www.itcbc.com:3006/api/getbooks",
// {
// params: {
// appkey: 'wanshao1234'
// }
// }).then(result=>{
// console.log(result);
// })
// axios.post(url,date) 地址 参数(对象)
// axios.post("http://www.itcbc.com:3006/api/addbook",{
// bookname: '从入门到精通',
// author: '我自己',
// publisher: '黑马出版社',
// appkey: 'wanshao1234',
// }).then(result=>{
// console.log(result);
// })
// axios.post(url,date) 地址 字符串
const str = "bookname=从入门到出去123&author=我自己&publisher=黑马出版社&appkey=wanshao1234"
axios.post("http://www.itcbc.com:3006/api/addbook",str).then(result=>{
console.log(result);
})
</script>
axios拦截器
为什么要添加拦截器
有时候用户上传的文件或者图片有些大,网络又不好,上传时网页一点反应都没有对用户不友好,从而导致用户以为没提交导致一直提交,浪费服务器资源
<style>
img {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: none;
}
</style>
</head>
<body>
<img src="./images/1.gif" alt="">
<button>点击按钮</button>
<script src="./lib/axios.js"></script>
<script>
const button =document.querySelector("button");
// 发送请求的时候 都显示一个 加载中的友好提示
// 很多功能 都需要和服务器 交互 发送网络请求
// 上传头像 网络很慢、上传的文件很大
// 整个页面 没有相应的 状态
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
document.querySelector("img").style.display = "block";
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
document.querySelector("img").style.display = "none";
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
button.addEventListener("click",function() {
axios.get("http://www.itcbc.com:3006/api/getbooks",{params:{appkey:"wanshao1234"}})
.then(result=>{
console.log(result);
})
})
</script>
</body>
FormData和文件上传
- FormData 是一个浏览器对象。用于管理表单数据。
- 和 jQuery中的 serialize() 作用一样,用于快速收集表单数据
- 并且可以将创建的FormData对象直接提交给接口。
- 典型应用场景:FormData + Ajax 技术实现文件上传的功能。
使用方法
API方法
FormData和serialize的区别
报文
请求报文
请求报文规定了客户端以什么格式把数据发送给服务器
具体形式请看请求方式
响应报文
响应报文规定了服务器以什么格式把数据响应给客户端
http响应状态码
常见的http响应状态码
http响应状态码和业务状态码
原生ajax代码
XMLHttpRequest
是浏览器内置的一个构造函数
作用:基于new出来的XMLHttpRequest实例对象,可以发起Ajax请求
使用XMLHttpRequest发起get请求
实现的主要4个步骤
- 创建xhr对象
- 调用xhr.open()函数
- 调用xhr.send()函数
- 监听load事件
注意:load事件也可以放到前面
<script>
// 使用XMLHttpRequest发起get请求
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.调用xhr.open()函数 方法里写请求方式 get 或者post 后面写地址
xhr.open('get','http://www.itcbc.com:3006/api/getbooks');
// 3.调用xhr.send()函数
xhr.send();
// 4.监听load事件
xhr.addEventListener("load",function() {
console.log("获取成功");
// 把字符串转为对象格式输出
const obj = JSON.parse(this.response);
console.log(obj);
// console.log(this.response);
})
</script>
原生get请求携带参数
直接把参数拼接在url地址后
<script>
const xhr = new XMLHttpRequest();
xhr.open('get','http://www.itcbc.com:3006/api/getbooks?appkey=wanshao1234');
xhr.send();
xhr.addEventListener("load",function() {
const obj = JSON.parse(this.response);
console.log(obj);
})
</script>
原生post请求携带参数(字符串)
<script>
const xhr = new XMLHttpRequest();
xhr.open('post','http://api.tianapi.com/hsjz/index');
const data = {
key:'a9f05bcff5d2146e5c44f358baad4bf1',
content:'假如生活欺骗了你,操翻他'
};
// 把data转成a=1&b=2...格式 URLSearchParams
const usp = new URLSearchParams(data);
const query = usp.toString();
// 设置对应的content-type
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(query);
xhr.addEventListener('load',function() {
console.log(this.response);
})
</script>
原生post请求携带参数(json对象类型)
<script>
const xhr = new XMLHttpRequest();
xhr.open('post','http://www.itcbc.com:3006/api/addbook');
const data = {
appkey:'wanshao1234',
bookname:'假如生活欺骗了你',
author: "222222哈哈哈",
publisher: "33333033"
};
// 设置对应的content-type
xhr.setRequestHeader("Content-Type","application/json");
const str = JSON.stringify(data);
xhr.send(str);
xhr.addEventListener('load',function() {
console.log(this.response);
})
</script>
原生post请求携带参数(FormData)
<body>
<input type="file" accept="images/*">
<script>
const input = document.querySelector("input");
input.addEventListener("change", function () {
//获取本地文件
const file = this.files[0];
const formdata = new FormData();
//插入键 值 根据接口插入键
formdata.append("avatar", file);
const xhr = new XMLHttpRequest();
xhr.open('post', 'http://www.itcbc.com:3006/api/formdata');
//不用设置Content-Type
xhr.send(formdata);
xhr.addEventListener('load', function () {
console.log(this.response);
})
})
</script>
</body>
post请求参数类型对应的Content-Type值
封装原生ajax
ajax本质可以看作一个函数
传入的参数是一个对象
需要在ajax函数中写完原生ajax代码
原生封装get
<script>
// 1.ajax 本质可以看作一个函数
// 2.传入的参数是一个对象格式
// 3.需要在ajax函数中写完原生ajax代码
const opction = {
url:'http://www.itcbc.com:3006/api/getbooks',
type:'get',
data:'appkey=wanshao1234',
success(result){
console.log(result);
}
}
ajax(opction);
function ajax(config) {
const xhr = new XMLHttpRequest();
//open("请求的方式","请求地址") 如果是get请求 参数拼接在地址后面 记得加上?
xhr.open(config.type,config.url + '?' + config.data);
// send("写post方式可能要的参数")
xhr.send();
xhr.addEventListener("load",function() {
//返回响应的数据 this.response
// 为了更好的体验 把数据转成对象类型
const obj = JSON.parse(this.response);
config.success(obj);
})
}
</script>
原生封装get(不带参数)
<script>
const opction = {
url:'http://www.itcbc.com:3006/api/getbooks',
type:'get',
data:'appkey=wanshao1234',
success(result){
console.log(result);
}
}
ajax(opction);
//形参 用解构方法 获取到里面的数据 然后给参数加上默认值
function ajax({type,url,data="",success}) {
const xhr = new XMLHttpRequest();
// 封装的时候考虑到用户(可能带参数,可能不带参数)
//地址后面直接加?不带参数的话会识别出来 没有影响
xhr.open(type,url + '?' + data);
xhr.send();
xhr.addEventListener("load",function() {
const obj = JSON.parse(this.response);
success(obj);
})
}
</script>
原生封装get(对象参数)
<script>
ajax({
url: 'http://www.itcbc.com:3006/api/getbooks',
type: 'get',
data: {
appkey: 'wanshao1234',
bookname: '假如生活欺骗了你'
},
success(result) {
console.log(result);
}
});
function ajax({ type, url, data = "", success }) {
const xhr = new XMLHttpRequest();
//判断传入参数是不是对象
if (typeof data === 'object') {
data = new URLSearchParams(data).toString();
}
xhr.open(type, url + '?' + data);
xhr.send();
xhr.addEventListener("load", function () {
const obj = JSON.parse(this.response);
success(obj);
})
}
</script>
原生封装post
判断实例是不是 构造函数的 儿子是不是亲生的
实例 instanceof 构造函数
<body>
<input type="file" accept="images/*">
<script>
//判断实例是不是 构造函数的 儿子是不是亲生的
// 实例 instanceof 构造函数
//对象
// ajax({
// url: 'http://www.itcbc.com:3006/api/addbook',
// type: 'post',
// data: {
// appkey: 'wanshao1234',
// bookname: '假如生活欺骗了你',
// author: "222222哈哈哈",
// publisher: "33333033"
// },
// success(result) {
// console.log(result);
// }
// });
// 字符串
// ajax({
// url: 'http://www.itcbc.com:3006/api/addbook',
// type: 'post',
// data:"bookname=%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E7%B2%BE%E9%80%9A111&author=%E6%88%91%E8%87%AA%E5%B7%B1&publisher=%E9%BB%91%E9%A9%AC%E5%87%BA%E7%89%88%E7%A4%BE&appkey=wanshao1234",
// success(result) {
// console.log(result);
// }
// });
// FormData对象
const input = document.querySelector("input");
input.addEventListener("change",function() {
//获取本地文件
const file = this.files[0];
const formdata = new FormData();
//插入键 值 根据接口插入键
formdata.append("avatar", file);
ajax({
url: 'http://www.itcbc.com:3006/api/formdata',
type: 'post',
data:formdata,
success(result) {
console.log(result);
}
});
})
function ajax({ type, url, data = "", success }) {
const xhr = new XMLHttpRequest();
//判断请求类型
if (type === 'get') {
//判断输入参数类型
if (typeof data === 'object') {
data = new URLSearchParams(data).toString();
}
xhr.open(type, url + '?' + data);
xhr.send();
} else if (type === 'post') {
xhr.open(type, url);
//判断参数是不是字符串
if (typeof data === 'string') {
// 设置对应的content-type
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);
} else if (typeof data === 'object') {
//判断参数是不是对象
//判断参数是不是FormData
if (data instanceof FormData) {
xhr.send(data);
} else {
//普通的对象
xhr.setRequestHeader("Content-Type", "application/json");
const str = JSON.stringify(data);
xhr.send(str);
}
}
}
xhr.addEventListener("load", function () {
const obj = JSON.parse(this.response);
success(obj);
})
}
</script>
</body>
数据交换格式JSON
JSON(全称:JavaScript Object Notation)是一种数据交换格式,它本质上是用字符串的方式来表示对象或数组类型的数据。
JSON数据的格式
- 对象格式
- 数组格式
语法要求
- 属性名必须使用双引号包裹
- 字符串类型的值必须使用双引号包裹
- JSON 中不允许使用单引号表示字符串
- JSON 中不能写注释
- JSON 的最外层必须是对象或数组格式(其他类型也可以,但多数是对象或数组格式)
- 不能使用 undefined 或函数作为 JSON 的值
对象格式的JSON数据
数组格式的JSON数据
把JSON格式的字符串转为JS数据
JSON.parse()
JS 数据转换为 JSON 格式的字符串
JSON.stringify()
防抖(debounce)
核心就是利用了延时器
技术原理
用新的一次输入来清除上一次的延时器
同时开启一个信的延时器
指的是:频繁触发某个操作时,只执行最后一次
应用场景
搜索框只在输入完后,才执行查询的请求。
好处
这样可以有效减少请求的次数,节省网络资源。
<body>
<input type="text" />
<table>
<thead>
<tr>
<th>id</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script src="./lib/axios.js"></script>
<script>
/*
防抖 防止抖动
1 用在输入框中 实现 不用用户按下回车键 就发送请求
2 技术原理
1 用新的一次输入来清除上一次的延时器
2 同时开启一个新的延时器
*/
getData();
// change事件 输入框的值发生改变-输入框失去焦点 才触发
// input 事件
// 定义一个 演示器 id
let timeid; // 钻 石 城 堡
const input = document.querySelector('input');
input.addEventListener('input', function (event) {
clearTimeout(timeid);
// 开启了一个延时器 里面代码 1s后会执行
timeid = setTimeout(function () {
const value = input.value.trim();
const queryStr = `?bookname=${value}`;
getData(queryStr);
}, 1000);
});
function getData(query = '') {
axios({
method: 'get',
url: 'http://www.itcbc.com:3006/api/getbooks' + query,
// params:{},
}).then((result) => {
console.log(result);
const arr = result.data.data;
render(arr);
});
}
function render(arr) {
let html = arr
.map(
(value) => `
<tr>
<td>${value.id}</td>
<td>${value.bookname}</td>
<td>${value.author}</td>
<td>${value.publisher}</td>
</tr>
`
)
.join('');
document.querySelector('tbody').innerHTML = html;
}
</script>
</body>
节流
指的是:单位时间内,频繁触发同一个操作,只会触发一次
应用场景
上一次请求还没结束就不能开启下一个请求
移动端分页、射击游戏中,单位时间内只能发射一颗子弹。
<body>
<button>获取数据</button>
<script src="./lib/axios.js"></script>
<script>
/*
节流
上一次的业务没有结束的话 不允许开启下一次业务
使用场景 移动端分页 - 倒计时按钮 等等
*/
// 这一次请求还没有结束 就不能开启下一个请求
// 业务 分页 业务
// 开关
let isLoadding = false; // 有没有请求在发送当中
// 点击按钮的时候先判断 isLoadding true还是false
// true 请求在发送中 return
// false 没有请求
// 先设置 isLoadding true
// 发送请求出去
// 请求回来了 设置 isLoadding = false
document.querySelector('button').addEventListener('click', function () {
if (isLoadding) {
return;
}
isLoadding = true;
// 发送请求的时候 禁用按钮
// this.disabled=true;
getData();
});
function getData(query = '') {
console.log('请求发送出去');
axios({
method: 'get',
url: 'http://www.itcbc.com:3006/api/getbooks' + query,
// params:{},
}).then((result) => {
console.log('数据回来了');
// document.querySelector('button').disabled=false
isLoadding = false;
});
}
</script>
</body>