AJAX学习
Ajax的概念:
Ajax用来实现客户端网页请求服务器的数据,当用户有操作时可以实时更新部分模块或者整个网页
先引入axios库 官网:http://www.axios-js.com/
axios基本语法:
模板:
axios({
method: '',
url: '',
}).then((result) => {
//.then 用来指定请求成功之后的回调函数
// 形参中的result是请求成功之后的结果
});
then方法(或回调函数)负责接受发过来的数据
属性区分大小写
axios GET 请求:
axios({
method: '请求的类型',
url: '请求的URL地址',
params: {id: 1, bookname: '红楼梦'}
// params用于传递参数,可选
}).then((result) => {})
Demo:为button绑定一个click事件并发送get请求,注意params可省
$('button').on('click', function() {
axios({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks',
params: {
id: 3
},
}).then(result => { //then控制请求成功
console.log(result.data.data);
}).catch(err => { //catch控制请求失败(扩展)
get参数的本质就是把所有属性用=链接、&符号分隔、放到路径的最末尾(前面要加?)
Demo:
http://www.liulongbin.top:3006/getbook?id=1&bookname=红楼梦
注意不能有空格和中文等特殊字符,浏览器会对URL的中文进行编码处理
编码和解码

axios的解构赋值
axios({
method: 'GET',
url: 'http://www.liulongbin.top:3009/api/getbooks'
}).then(({data: res}) => {
// 从 .then(fn) 回调函数的形参中,解构赋值出 data 属性,重命名为 res
console.log(res)
})
因为ajax拿的参数中最重要的就是data,在then回调函数中通过对象解构把data的参数赋值到一个res的变量中(名称随意),然后对这个json进行操作
then返回的数据:
axios POST 请求:
POST请求一定得有参数,因为POST就是推数据给服务器
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3009/api/addbook',
data: { //post用的是data传递请求参数
bookname: '三体',
author: '刘慈欣',
publisher: '北京人民出版社'
},
}).then(({data: res}) => {
console.log(res);
})
请求报文和响应报文
客户端发请求给服务器,请求报文规定数据格式
服务器回数据,响应报文规定数据格式



注意的是响应码和状态码不同,下面展示的是响应码
响应码由
http协议制定,一般都约定俗成状态码不唯一,在接收到的数据中,可以由后端人员自己定义;就好比客户端无法请求数据大部分都返回
404
响应状态码表示与服务器端的通信请求是否成功,而状态码表示业务处理的状态,一般会由后端给你写在接口文档里,供需要时查阅
Ajax表单数据提交
Ajax表单数据提交一般的表单分为三个模块:表单标签form、表单域(input、textarea、select),表单按钮(submit或reset)
- 表单的作用就是收集数据
阻止默认行为:
$('form').on('submit', function (e) {
e.preventDefault();
})
为什么需要阻止默认行为?
默认的表单元素如果没有action参数,也就是没有设置url的话默认会刷新页面,设置了就会跳转,如果只是收集数据,我们应该阻止浏览器默认行为
Jquery 中的 serialize 方法:
$('form').serialize()方法会拿表单中所有的带name属性的数据,以a=1&b=2(只是举例)这样的字符串数据类型发送请求
利用 serialize 请求数据:
$('form').on('submit', function(e) {
e.preventDefault();
axios.post('http://www.liulongbin.top:3009/api/form', $('form').serialize()
).then(({data: res}) => {
console.log(res);
})
})
细看请求包:
关注两个点就行:
application后面是/x-www-form-urlencoded(一般形式的get和post请求回的包都是json类型)data是以字符串形式传参的
使用 别名传参:
axios.get('http://www.liulongbin.top:3009/api/get').then(res => {
console.log(res.data);
})
axios.post('http://www.liulongbin.top:3009/api/post', {name: '123',}).then(res => {
console.log(res.data);
})
- 注意的是用
post必须得有参数,而且第二个(data)参数可以是{}对象这种,也可以是json或者FormData等变量
其他别名(就是懒人语法/语法糖):
axios.delete(url,[]);
axios.put(url,[data{}])
axios.patch(url,[]);
全局配置根路径:
也是语法糖,但是有优点,项目里可以经常用,易于维护而不需要大量修改
方法①:
语法
axios.interceptors.request.use(function(config) {
config.url = '根路径url' + config.url
return config;
})
方法②:
拦截器
axios.interceptors.request.use(function(config) {
config.url = '根路径url' + config.url
return config;
})
axios拦截器:
axios拦截器:
在代码中: 拦截器配置在axios文件的下面script语句的前面
语法格式:
axios.interceptors.request / response.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
- 注意
use中放两个函数就行,一个成功干什么,一个错误干什么
FormData:
FormData是浏览器的一个Web Api,它是一个原生DOM! FormData配合ajax,能够向浏览器发送multipart/form-data编码格式的数据,一般用于文件上传
FormData是一个构造函数,使用new可以拿到FormData对象
const fd = new FormData()
利用表单点击事件拿到FormData对象(注意的是用的原生DOM)
let form = document.querySelector('form');
form.addEventListener('submit', function(e) {
e.preventDefault();
let fd1 = new FormData(form);
console.log(...fd1);
})
调用FormData对象的append(键,值)方法
fd.append(‘username’, ‘Lion’)
注意键名必须是字符串
使用FormData请求一次数据:
const fd = new FormData;
fd.append('name', 'Lion');
fd.append('value', 'is man'
axios.post('http://www.liulongbin.top:3009/api/formdata', fd).then(({data: res}) => {
console.log(res);
})
细看请求包,确认传参成功:

数据交换原理
JSON数据类型:
全称:JavaScriptObjectNotation
可以理解为一个键值对都是字符串的数据格式,在C++、python等多种语言中都有这种数据类型
服务器和客户端常用的两种数据交换格式为:XML和JSON;早期则是XML、目前主流格式为JSON
JSON数据的格式:
可以是: 对象、数组、布尔值、null
不可以是: undefined、function
JSON语法要求`:
- 属性名必须使用双引号
- 不允许单引号表示字符串
- 不能写注释
- 最外层必须是对象或者数组
JSON 中 Ajax 常用方法:
反序列化: JSON格式转JS数据
JSON.parse()
序列化:JS数据转JSON格式;为前一个方法的逆运算
JSON.stringgify()

Ajax底层 ==> XMLHttpRequest
- 什么是
XMLHttpRequest?
是浏览器内置的一个构造函数(也就意味着它是原生的);也是ajax的核心对象
axios中的get、post,包括axios本身都是基于它(简称XHR)封装出来的
不用axios,自己用XHR也是可以给服务器发包的
分为四步:
- 实例化
xhr - 调用
xhr.open()指定请求方法 - 调动
xhr.send()发送数据 - 监听
load事件并用xhr.response()方法接受响应报文
使用xhr发送GET:
document.querySelector('button').onclick = function() {
const xhr = new XMLHttpRequest();
xhr.open('GET','http://www.liulongbin.top:3009/api/get');
xhr.send();
xhr.addEventListener('load', function() {
console.log(JSON.parse(xhr.response));
//接受过来的数据是纯字符串,转换成JSON更清晰
})
}
使用xhr发送POSt:
document.querySelector('button').onclick = function() {
const xhr = new XMLHttpRequest();
xhr.open('POST','http://www.liulongbin.top:3009/api/post');
xhr.send('name: David');
xhr.addEventListener('load', function() {
console.log(JSON.parse(xhr.response));
})
}
注意:send默认只发送字符串格式的参数,除非传参FormData变量或者setRequestHeader手动指定报头
也可以使用类似HTML表单标签的方式设置请求类型发送POST:
JSON:
document.querySelector('button').onclick = function() {
const xhr = new XMLHttpRequest();
xhr.open('POST','http://www.liulongbin.top:3009/api/post');
xhr.setRequestHeader('content-type', 'application/json');
//大小写无所谓,浏览器会做处理
xhr.send(`{"name": "David", "age": "18"}`);
//JSON必须键值对都用双引号
xhr.addEventListener('load', function() {
console.log(JSON.parse(xhr.response));
})
}
Request Headers:
字符串(a=1&b=2这种):
document.querySelector('button').onclick = function() {
const xhr = new XMLHttpRequest();
xhr.open('POST','http://www.liulongbin.top:3009/api/post');
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
//大小写无所谓,浏览器会做处理
xhr.send('name=David&age=18');
//字符串参数
xhr.addEventListener('load', function() {
console.log(JSON.parse(xhr.response));
})
}
Request Headers:

注意:如果漏写&z或者其他符号就会被浏览器认为是单个属性(键名),而就不是收到如上图所示的键值对形式了
FormData:
document.querySelector('button').onclick = function() {
const fd = new FormData();
fd.append('name', 'David');
fd.append('age', '18');
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.liulongbin.top:3009/api/post');
xhr.send(fd);
//无需设置setRequestHeader, 默认转换
xhr.addEventListener('load', function() {
console.log(JSON.parse(xhr.response));
})
Request Headers:
注意:load事件是异步任务,位置可以随意放置
Jquery 中的 Ajax:
Jquery中对于ajax封装了三个方法:
$.get() | $.post() | $.ajax()
- 与
axios有一些不同 - (因为
axios是基于Jquery的ajax方法改进而成的)
$.get():
$.get('http://www.liulongbin.top:3009/api/getbooks',{id:2},
function(res) {
console.log(res);
})
$.post()
$.post('http://www.liulongbin.top:3009/api/addbook',{
bookname: 'djy', author: 'dsy', publisher: '谁知道'
}, function(res) {
console.log(res);
})
$.ajax()
$.ajax({
method:'post',
url: 'http://www.liulongbin.top:3009/api/addbook',
data: {
bookname: 'dsypig',
author: 'dsypig',
publisher: '谁知道'
},
success: function(res) {
console.log(res);
}})
区分:
then被success替代success的形参不需要结构,直接返回值的data部分- 请求参数不似
axios不分区get的params和post的data jquery中的拦截器必须自己手动设置,跟axios的不为同一个!
利用$ajax.()实现上传文件(或者发送FormData对象)
jQuery中的ajax比较特殊,上传文件(或者说发送FormData对象)必须带两个参数:
contentType: false //取消默认设置文件头信息
processData: false //取消对文件默认的编码
利用$ajax.()实现CORS跨域
$ajax({
dataType: 'jsonp'
//json | text | html | xml | script
})
dataType:改变底层的请求方式和请求报头,不再让它使用XHR、而是使用script标签发包(script标签不与同源策略冲突)并且返回值是jsonp格式(也可以指定其他返回格式)
返回值格式:

同源策略:
- 什么是同源?
同源值得是两个URL地址具有相同的协议、主机名、端口号
如果不同源直接发包,则是跨域请求
http的默认端口是80、https是443 默认不写浏览器也能识别
- 为什么会有跨域?
浏览器的安全策略:
它不允许非同源的URL进行资源交互
跨域的请求会被放行,但是响应包会被拦截
跨域的解决方案:
| 方案 | 诞生的时间 | 方案来源 | 优点 | 缺点 |
|---|---|---|---|---|
| JSONP | 出现较早 | 民间 | 兼容性好 | 仅支持get请求 |
| CORS | 出现较晚 | W3C | 支持五种常见请求方式 | 兼容性 |
CORS是跨域的主流技术解决方案,但是面试官喜欢JSONP
深入:
CORS用到了XMLHTTPRequest对象,是纯正的ajax请求
JSONP没有用XMLHTTPRequest对象,是偏方
只要涉及和用到了XMLHTTPRequest,就是ajax请求
底层:
CORS(后端方案、我暂时不研究):
JSONP(需要后端配合的方案):
JSONP在底层是用到了script标签的src属性,script标签的src属性不受同源策略限制,与之类似的还有a标签的跳转、img的src,它是把非同源的src请求到本地然后执行
<script src="http://www.liulongbin.top:3009/api/jsonp?callback=showInfo&name=david">
</script>
<script>
function showInfo(res) {console.log(res);}
</script>
因为script标签只能发送get请求,而且在工作中前端和后端要约定一致一个函数名,对不上会出问题,还可以在标签里写callback回调函数的形式告诉后端要返回什么样的函数名、以及传少量的字符串参数
防抖和节流
防抖是指频繁触发某个操作只执行最后一次
实现:
- 定义一个延时器
- 事件开始之前清除延时器
- 触发事件后延迟一段时间,如果没有继续被触发,则执行回调函数;如果又被触发,重新计时
节流是指单位时间内某个操作只执行触发一次
实现:
执行函数时,if判断某种状态或者计时,如果未满足条件或者计时器没有结束则return;如果条件为真或者到单位时间设置flag为true;继续执行下面的函数