Ajax
1. URL网址的基本概念
- URL概念:统一资源定位符 (Uniform Resource Locator)
- 俗称网址,用来标识某个资源在网络中的唯一位置。
- 组成部分:
- 示例网址:https://detail.tmall.com/item.htmid=555428842095
- 通信协议: https://
- 域名(服务器地址): detail.tmall.com
- 资源(文件)的具体位置: /item.htm?id=555428842095
2. 请求和响应的流程
- 任意的一次网络访问(访问网站根目录、img加载、audio加载、link标签…)都是下面的3个步骤
- 步骤
- 1 请求:客户端请求服务器
- 2 处理:服务器的内部处理(找找资源等…)
- 3 响应:服务器响应客户端
2.1. 浏览器的network面板的使用
network用来检测浏览器发出的每次请求以及响应内容
- 打开方式:浏览器 -> F12 -> Network -> 进行操作
- 左侧为所有请求的请求列表
- 顶部具有请求的筛选功能
- 选择某一条请求后,可以查看请求的具体内容
- request 请求
- response 响应
3. 网站中的资源
- 常见资源为:图片、文字、音视频、css文件…
- 核心资源:数据(根据数据生成页面结构可以让页面制作变简便,维护成本降低)
- 与html、css、js的关系
- html是网页的结构、骨架
- css是网页的样式、颜值
- js是网页的行为、控制交互
- 数据是网页灵魂
4. 资源的请求方式get post
- 请求类型:get() post()
- 语义的区别
- get 用来进行获取资源的请求操作
- 获取图片、音视频、js文件、css文件、地址栏输入地址回车,location.href,a标签跳转。。。
- post 用来进行发送资源的请求操作
- 表单提交form标签(get、post均可,可以自己选择)
- ajax也可以发送get和post请求
- get 用来进行获取资源的请求操作
- 可发送数据大小有区别
- get请求受限制于浏览器对url的限制,2M左右
- post请求理论上无大小限制,实际上受限制于服务端实际的业务需求和处理能力
- 可发送的数据格式有区别
- get请求只能发送文本格式数据
- post请求不限制发送的数据格式,服务器会根据业务需求进行处理
4.1. 传统请求发送方式
- 地址栏
- a标签
- location.href
- img.src link.href 我们无法进行干预
- form+submit
上面发送请求的方式,统一特点:都会出现跳转(有的是我们无法干预的)
实际页面功能制作时,很多的功能虽然请求了新的数据,但是并没有出现跳转,只是局部刷新
结论:传统的请求方式无法满足现代网页的所有功能,就需要使用新的请求方式----AJAX。
5. AJAX简介
Ajax(Asynchronous Javascript And XML(异步 JavaScript 和 XML))
- 作用:用来发送请求的一种方式
- 实现方式:浏览器提供了一个XMLHttpRequest的构造函数,创建的对象用来进行ajax操作
- 特点:无需刷新页面,也可以进行请求响应处理(局部刷新)
5.1. 同步和异步的概念
同步任务:
- 执行顺序:代码按顺序从上往下一个一个执行。
- 除了异步任务都是同步任务。
异步任务:
- 为什么要有异步任务: 因为某些任务较为耗时,或执行时间不确定,为了避免卡住(阻塞)后续代码,设置为异步任务。
- 常见异步任务有:
- 定时器
- 示例:无论定时器的时间为多少,都会比同步任务执行晚。
- Ajax
- 定时器
- 执行顺序:异步任务的执行一定晚于同步任务
5.2.js语言特性和单线程
js的语言特性
- js是弱类型语言
- js是动态语言
- js是脚本语言
- js是基于对象的语言(面向对象语言)
- js是基于原型的语言
- js是事件驱动的语言
- js是单线程的语言
单线程(只有一个人干活)
- 因为js中具有DOM操作,例如修改元素颜色,单个线程操作不会与其他线程产生干扰冲突
- es5后js也出现了多线程的概念,但是有限制,多个线程只能进行辅助操作,主线程进行控制
多线程(有好多人干活)
6. jQuery中的ajax操作
6.1. $.get()的使用
没有请求参数,不接收响应数据
$.get(地址); // 通过浏览器调试工具的network查看请求的细节和响应的数据
$.get('http://www.liulongbin.top:3006/api/getbooks');
没有请求参数,接收响应数据
$.get(地址, function(res) {
// 响应接收完毕后,执行回调函数
// res代表响应的数据,如果res为JSON格式,jQuery会自动转换为js对象
});
$.get('http://www.liulongbin.top:3006/api/getbooks', function (res) {
// 响应完成后,触发这个回调函数
// 回调函数的参数表示响应的数据,一般称为response或res
console.log(res);
});
有请求参数,接收响应数据
请求参数:请求中发送给服务端的数据,是一个对象
$.get(地址, 请求参数组成的对象, 回调函数);
$.get('http://www.liulongbin.top:3006/api/getbooks', { id: 2 }, function (res) {
console.log(res);
});
6.2. $.post()的使用
没有请求参数,不接收响应数据
$.post(地址); // 通过浏览器调试工具的network查看请求的细节和响应的数据
$.post('http://192.168.141.45:3005/common/post');
没有请求参数,接收响应数据
$.post(地址, function(res) {
// 响应接收完毕后,执行回调函数
// res代表响应的数据,如果res为JSON格式,jQuery会自动转换为js对象
});
$.post('http://192.168.141.45:3005/common/post', function (res) {
console.log(res);
})
有请求参数,接收响应数据
请求参数:请求中发送给服务端的数据,是一个对象
$.post(地址, 请求参数组成的对象, 回调函数);
$.post(
'http://192.168.141.45:3005/common/post',
{ name: 'jack', age: 18 },
function (res) {
console.log(res);
});
6.3. $.ajax()的使用
- type表示请求方式,默认为’GET’,可以设置为’GET’/‘POST’
- url表示请求地址,只有url属性是必须设置的
- data表示请求参数,对象结构
- success表示响应成功时的处理函数,res参数,表示响应内容
1.使用$.ajax()发送GET请求
$.ajax({
// type: 'GET', // 默认为GET,一般发送GET请求时,都不设置type
url: 'http://192.168.141.45:3005/common/get',
data: {
name: 'jack',
age: 18,
gender: '男'
},
success: function (res) {
console.log(res);
}
});
- 使用$.ajax()发送POST请求
$.ajax({
type: 'POST',
url: 'http://192.168.141.45:3005/common/post',
data: {
width: 200,
height: 600,
bgc: 'red'
},
success: function (res) {
console.log(res);
}
});
$.get()
、$.post()
与 $.ajax()
的关系
$.ajax()
是jQuery中设置的一个用来进行ajax请求发送的方法 ,$.get()
、$.post()
只是调用了$.ajax()
实现的功能
7. 接口的概念
- 接口:
- 概念:指的是能够提供某种能力的事物。
- 应用程序编程接口(API)
- 概念:提供应用程序编程能力的事物
- WebAPI
- 浏览器提供的,与web开发相关的一些API,本质上就是一堆属性方法
- 内置对象API
- js解析器提供的,用于js基础语法操作的一些API,本质上就是一堆属性方法
- js的组成部分和浏览器的主要构成
- 浏览器的两个主要构成部分
- 内核(渲染引擎): html和css渲染,WebAPI
- js解析器:执行ECMAScript
- 规范相关内容:
- w3c规范:html css webAPI
- ECMA规范:语法(含内置对象)
- 浏览器的两个主要构成部分
- 数据接口:
- 概念:是能够提供数据的一种事物。表现形式就是一个URL
- 简单来说,能够提供数据的一个URL地址,就称为是数据接口
- 说明:当进行前端和后端(服务器)交互时,所说的’接口’,指的就是数据接口。
- 使用方式:严格遵守接口的文档进行操作即可。
- 概念:是能够提供数据的一种事物。表现形式就是一个URL
8. 时间戳格式化方法
// 用来将时间戳进行日期格式化的函数:
function dateFormat(timestamp) {
var time = new Date(parseInt(timestamp));
var y = time.getFullYear();
var m = time.getMonth() + 1;
m = m > 9 ? m : '0' + m;
var d = time.getDate();
d = d > 9 ? d : '0' + d;
var h = time.getHours();
h = h > 9 ? h : '0' + h;
var mm = time.getMinutes();
mm = mm > 9 ? mm : '0' + mm;
var s = time.getSeconds();
s = s > 9 ? s : '0' + s;
return y + '-' + m + '-' + d + ' ' + h + ':' + mm + ':' + s;
}
var time=1575808501208; // -------时间戳
time=dateFormat(time);
9. 表单form
表单在网页中主要负责数据采集功能。HTML中的标签,就是用于采集用户输入的信息 ,
由于标签的submit提交操作会发生跳转,用户体验很差,页面之前的状态和数据会丢失。
经常使用表单进行数据采集(用输入框等元素获取输入内容),使用ajax进行请求发送即可(提交)
9.1. 表单的组成部分
-
form标签
-
表单域:input标签。。textarea。。select…
-
提交按钮:
<input type="submit"> <button type="submit">提交</button>
- 如果希望button不进行提交操作,只是普通按钮,可以设置type为button
9.2. form标签的属性
标签的属性则是用来规定如何把采集到的数据发送到服务器。
- action
- action 属性的值是一个URL地址,定义向何处提交表单,默认值为当前页面的 URL 地址。
- 注意:当提交表单后,页面会立即跳转到 action 属性指定的 URL 地址。
- target
- 规定在何处打开 action URL。
- _self 默认在本窗口打开 _blank在新窗口打开
- method
- 规定以何种方式把表单数据提交到 action URL ,get和post
- enctype
- 规定在发送表单数据之前如何对数据进行编码
- 在涉及到文件上传的操作时,必须将 enctype 的值设置为 multipart/form-data
9.3. 表单操作的特点
- 提交数据时会出现页面跳转的情况
- 提交后,页面之前的状态和数据会丢失。
9.4. 常用请求方式
- 使用表单进行数据采集(用输入框等元素获取输入内容),使用ajax进行请求发送即可(提交)
10. 表单和ajax结合使用
10.1. 监听表单提交事件
在 jQuery 中,可以使用如下两种方式,监听到表单的提交事件:
$('#form1').submit(function(e) {
alert('监听到了表单的提交事件')
})
$('#form1').on('submit', function(e) {
alert('监听到了表单的提交事件')
})
10.2. 阻止表单的默认提交行为
在submit事件中,设置e.preventDefault()方法即可(推荐), return false也可以
$('#form1').submit(function(e) {
// 阻止表单的提交和页面的跳转
e.preventDefault()
})
$('#form1').on('submit', function(e) {
// 阻止表单的提交和页面的跳转
e.preventDefault()
})
10.3. serialize()快速获取表单中的数据
jQuery的serialize()方法可以快速获取表单中的所有数据(只能获取纯文本数据)
为了简化表单中数据的获取操作,jQuery 提供了 serialize() 函数,其语法格式如下 :
$(selector).serialize()
serialize() 函数的好处:可以一次性获取到表单中的所有的数据。
<form id="form1">
<input type="text" name="username" />
<input type="password" name="password" />
<button type="submit">提交</button>
</form>
$('#form1').serialize()
// 调用的结果:
// username=用户名的值&password=密码的值
注意:在使用 serialize() 函数快速获取表单数据时,必须为每个表单元素添加 name 属性!
- 注意:这种内容格式可以通过
$.get $.post $.ajax
进行直接发送 - 注意表单元素如果没有name,数据是无法正确提交的
11. XMLHttpRequest
XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,通过它,可以请求服务器上的数据资源。
jQuery 中的 Ajax 函数,就是基于 xhr 对象封装出来的.
12. get请求
12.1. get请求基本使用
步骤:
- 创建xhr对象
- 调用xhr.open():设置请求方式和请求地址
- 调用xhr.send(): 发送请求(这一步是异步操作)
- 设置onreadystatechange事件,监听请求的各种状态
- readyState是xhr的属性,用来表示请求发送的状态
- 取值为4代表下载完毕
- 必须确保readyState为4才能使用响应的数据
- xhr.status 代表请求是否成功
- 200代表请求是成功的
- xhr.responseText 代表接收的响应内容
- readyState是xhr的属性,用来表示请求发送的状态
// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 调用xhr.open():设置请求方式和请求地址
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
// 3 调用xhr.send(): 发送请求,这一步是异步操作
xhr.send();
// 4 设置事件,监听请求的各种状态
// readyState是xhr的属性,用来表示请求发送的状态
// 取值为4代表下载完毕
// 必须确保readyState为4才能使用响应的数据
// 进一步检测:
// xhr.status 代表请求是否成功
// 200代表请求是成功的
xhr.onreadystatechange = function () {
// 4.1 检测xhr.readyState取值和xhr.status取值
if (xhr.readyState === 4 && xhr.status === 200) {
// 4.2 接收响应的数据即可
// 原生接收的响应内容是JSON格式,需要自己进行转换
// jQuery会自动转换
console.log(xhr.responseText);
}
};
12.2. 带有参数的get请求
-
位置:在xhr.open()的参数2 url后面书写参数内容
-
名称:参数的形式称为查询字符串
-
格式: ?名=值&名=值…
- 其中 名=值&名=值… 称为url编码格式,英文为urlencoded
-
jQuery的get请求和原生get请求的本质是一样的
// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 调用open:设置请求方式和请求地址
// 如果希望设置get请求的请求参数,需要放置在open()参数2地址的最后位置
// 书写方式为: 地址?名=值&名=值....
// 名称说明: 名=值&名=值称为url编码格式 urlencoded
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=3&name=jack&age=18');
// 3 调用send: 发送请求,这一步是异步操作
xhr.send();
// 4 设置事件,监听请求的各种状态
xhr.onreadystatechange = function () {
// 4.1 检测xhr.readyState取值和xhr.status取值
if (xhr.readyState === 4 && xhr.status === 200) {
// 4.2 接收响应的数据即可
console.log(xhr.responseText);
}
};
13. xhr对象的readyState属性
XMLHttpRequest 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态。
每个 Ajax 请求必然处于以下状态中的一个:
值 状态 描述
0 unsent XMLHttpRequest对象已被创建,但尚未调用open()方法
1 opened open()方法已经被调用
2 headers_received send()方法已经被调用,响应头也已经被接收
3 loading 数据接收中
4 done Ajax请求完成,下载完毕
14. url编码
URL 地址中,只允许出现英文相关的字母、标点符号、数字,因此,在 URL 地址中不允许出现中文字符。
如果 URL 中需要包含中文这样的字符,则必须对中文字符进行编码(转义)。
URL编码的原则:使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。
URL编码原则的通俗理解:使用英文字符去表示非英文字符。
- url编码是url对地址的一种处理方式(将中文部分进行编码转换)
- 浏览器会进行自动的url处理,无需我们自己操作
- 两个用来处理的函数
- encodeURI() 编码
- decodeURI() 解码
// 使用encodeURI() 对内容进行编码
console.log(encodeURI('黑马程序员'));
console.log(encodeURI('传智播客'));
// 使用decodeURI() 对内容进行解码
console.log(decodeURI('%E9%BB%91%E9%A9%AC%E7%A8%8B'));
console.log(decodeURI('%E5%BA%8F%E5%91%98'));
15. post请求的发送方式
步骤:
- 创建xhr对象
- 调用xhr.open()
- 设置Content-Type(内容格式、内容类型)
- xhr.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’)
- 调用xhr.send(数据)
- 数据为url编码格式
- 设置readystatechange事件获取响应内容
// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 调用xhr.open()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook');
// 3 设置Content-Type内容格式(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 4 调用xhr.send()
// - 如果具有请求参数,书写在send中,格式也是url编码格式(名=值&名=值...)
xhr.send('bookname=老人与海&author=海明威&publisher=大海图书出版社');
// 5 设置readystatechange事件,接收响应的数据
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
16. get与post发送方式的区别
请求参数的书写位置不同:
- get请求方式:在xhr.open()的url后面使用?连接
- post请求:在xhr.send()中书写
post请求需要设置Content-Type
17. 封装ajax函数
封装用来将对象转换为url编码的函数
// 封装函数,用于将对象转换为url编码格式
function urlencoded(obj) {
var arr = []; // 声明数组用来保存结果
// 遍历obj,获取所有属性
for (var k in obj) {
// k - 属性名 - 字符串类型
// obj[k] - 属性值
arr.push(k + '=' + obj[k]);
}
return arr.join('&');
}
封装ajax函数
- 转换字符串为大小写的字符串方法
- 字符串.toUpperCase() 转换为大写字母
- 字符串.toLowerCase() 转换为小写字母
// 封装用来发送ajax请求的函数
// 参数:
// 对象
// - type 请求方式
// - url 请求地址
// - data 请求参数
// - success 回调函数
function ajax(options) {
// 1 创建xhr对象
var xhr = new XMLHttpRequest();
// 2 设置请求的相关信息: 需要根据请求方式分别设置
// 统一保存数据
var data = urlencoded(options.data);
// 2.1 将请求方式统一转换为大写(或小写)
var type = options.type.toUpperCase();
// 2.2 对请求方式进行检测
if (type === 'GET') {
xhr.open('GET', options.url + '?' + data);
xhr.send();
} else if (type === 'POST') {
xhr.open('POST', options.url);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(data);
}
// 3 设置事件接收响应内容
xhr.onreadystatechange = function () {
// 3.1 检测
if (xhr.readyState === 4 && xhr.status === 200) {
// 3.2 将JSON格式的字符串转换为对象
var res = JSON.parse(xhr.responseText);
options.success(res);
}
};
}
// 进行数据处理的函数
function urlencoded(obj) {
var arr = []; // 声明数组用来保存结果
// 遍历obj,获取所有属性
for (var k in obj) {
// k - 属性名 - 字符串类型
// obj[k] - 属性值
arr.push(k + '=' + obj[k]);
}
return arr.join('&');
}
可选:可以给ajax函数的options中的属性设置默认值
- type默认值为'GET'
- data默认为''
- success如果不存在,则不进行调用,避免报错
18. XMLHttpRequest Level2的新功能
可以设置 HTTP 请求的时限
可以使用 FormData 对象管理表单数据
可以上传文件
可以获得数据传输的进度信息
18.1. 设置HTTP请求时限
设置方式:
- 属性: xhr.timeout = 超时时间; // 毫秒单位
- 时间: xhr.ontimeout = function() { 请求超时后,触发的事件 };
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
// 设置请求的超时时间(毫秒单位)
xhr.timeout = 500;
// 设置事件,对超时进行处理
xhr.ontimeout = function () {
console.log('网络开小差了,请稍后再试!~');
};
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
18.2. FormData管理表单数据
FormData的作用:
- 可以快速处理表单的数据
- 可以进行文件上传
注意点:
- 发送FormData需要使用POST请求方式
- 不需要单独设置Content-Type
使用方式:
1.单独发送数据:创建空FormData对象,添加数据后发送
// 1.1 创建FormData对象
var fd = new FormData(); // 空的FormData对象
// 1.2 向fd中添加一些数据
fd.append('name', 'jack');
fd.append('age', 18);
// 1.3 使用POST方法将fd发送到对应接口(此处的接口为formdata)
// 无需设置之前post的content-type
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata');
xhr.send(fd); // 将fd放入在send()参数中即可
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
2.处理表单数据:通过form表单获取数据后发送
<!-- 设置form标签,用来进行formdata操作 -->
<form id="testForm">
<!-- 如果要表单元素数据被请求发送,必须设置name -->
<input type="text" name="username">
<input type="password" name="password">
<!-- 设置按钮,点击后,使用FormData处理表单数据 -->
<button type="button" id="btn">ajax提交</button>
</form>
// 2 通过FormData对象管理表单元素,再发送(同时也可以添加数据)
document.getElementById('btn').onclick = function () {
// 2.1 创建FormData对象,传入DOM对象形式的form标签到参数中
var testForm = document.getElementById('testForm');
var fd = new FormData(testForm); // 空的FormData对象
// 2.1.1 也可以在存在form的基础上,自己添加数据
fd.append('name', 'rose');
fd.append('age', 21);
// 2.3 使用POST方法将fd发送到对应接口(此处的接口为formdata)
// - 无需设置之前post的content-type
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata');
xhr.send(fd); // 将fd放入在send()参数中即可
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
}
18.3. 文件上传
- 1 准备结构(文件域)
<input type="file">
- 2 检测用户是否选择了文件
- 对DOM对象形式的
input[type="file"]
的files属性进行检测- 如果内部存储了任意的一个值,就说明选取了文件,否则就是没选
- 对DOM对象形式的
- 3 使用FormData保存文件信息
- 使用fd.append()添加即可
- 4 通过ajax发送
- 5 响应处理,展示服务端获取到的图片
<input type="file" id="iptFile">
<button type="button" id="btn">点击上传文件</button>
<img src="" alt="" id="pic">
// 1 给按钮设置点击事件
var btn = document.getElementById('btn');
var iptFile = document.querySelector('#iptFile');
var pic = document.getElementById('pic');
btn.onclick = function () {
// 2 检测是否上传了文件,需要检测文件域的files属性
// files是一个伪数组,可以通过判断length,检测是否选择了文件
if (iptFile.files.length === 0) {
// 说明没有选择文件
alert('请选择文件后提交!~');
return;
}
// 3 通过FormData保存文件信息
var fd = new FormData();
// avatar是接口中规定的请求参数名称
// files[0]代表选择的文件的相关信息
fd.append('avatar', iptFile.files[0]);
// 4 发送post形式的ajax,将fd发送给服务端处理
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar');
xhr.send(fd);
// 5 接收响应数据
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var res = JSON.parse(xhr.responseText);
// 5.1 检测上传是否成功
if (res.status === 200) {
// 5.2 将响应的图片在线地址,放入到img中展示
pic.src = 'http://www.liulongbin.top:3006' + res.url
}
}
}
};
jQuery使用FormData上传文件的注意点
- 必须设置两个属性
- contentType: false 不指定内容类型
- processData: false 不进行数据处理
18.4. 上传进度条功能
xhr.upload.onprogress 上传中实时触发事件
事件对象e的属性
- e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
- e.loaded 已传输的字节
- e.total 需传输的总字节
xhr.upload.onload 上传完毕时触发事件
/*
1 检测上传过程的事件
xhr.upload.onprogress = function(e) ...
2 检测文件大小是否可用
e.lengthComputable 布尔值
3 计算进度
e.loaded 已加载的大小
e.total 总大小
3.1 计算方式
e.loaded / e.total 上传的进度
制作进度条功能的思路:
- 设置内外两个盒子,外部盒子定宽度,内部盒子宽度默认为0
- 上传中,根据上传的进度设置内部盒子宽度对应改变即可
xhr.upload.onload 上传完毕后触发的事件
*/
var btn = document.getElementById('btn');
var iptFile = document.querySelector('#iptFile');
var pic = document.getElementById('pic');
btn.onclick = function () {
// 2 检测是否上传了文件,需要检测文件域的files属性
if (iptFile.files.length === 0) {
alert('请选择文件后提交!~');
return;
}
// 3 通过FormData保存文件信息
var fd = new FormData();
fd.append('avatar', iptFile.files[0]);
// 4 发送post形式的ajax,将fd发送给服务端处理
var xhr = new XMLHttpRequest();
// 设置上传文件的进度监测
xhr.upload.onprogress = function (e) {
// 判断e.lengthComputable是否为true,为true表示可以进行计算
if (e.lengthComputable) {
// 根据e.loaded和e.total计算进度比例
var bili = e.loaded / e.total * 100 + '%';
document.getElementById('percent').style.width = bili;
document.getElementById('percent').innerText = bili;
}
};
// 设置上传文件完成的事件(更改样式)
xhr.upload.onload = function () {
document.getElementById('percent').className = 'progress-bar progress-bar-success';
}
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar');
xhr.send(fd);
// 5 接收响应数据
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var res = JSON.parse(xhr.responseText);
// 5.1 检测上传是否成功
if (res.status === 200) {
// 5.2 将响应的图片在线地址,放入到img中展示
console.log(res);
}
}
}
};
19. jQuery的全局ajax处理器
作用:用来对页面中的ajax操作进行统一设置,简化操作
常见场景:加载资源的loading功能
ajaxStart() 任意请求开始时触发内部回调
//使用全局ajax处理器检测请求发送的操作,并将loading图展示
$(document).ajaxStart(function () {
// console.log('发送了ajax请求');
$('img').show();
});
ajaxStop() 任意请求结束后触发内部回调
//使用全局ajax处理器检测请求完毕的状态,并将loading图隐藏
$(document).ajaxStop(function () {
$('img').hide();
});
在ajax内部自己封装加载资源的loading功能
$("#btn").on("click", function() {
$("img").show(); //在请求开始之前将loading图展示
$.ajax({
url: "http://www.liulongbin.top:3006/api/getbooks",
success: function(res) {
$(".box").html(JSON.stringify(res));
$("img").hide(); //请求完毕,并将loading图隐藏
}
})
})
20. 同源策略和跨域
20.1. 同源(同源地址)
指的是两个页面地址的 协议 域名 端口 完全一样,这两个地址就是同源的,或者称为同源地址。
- 我们发现,在现代网站中(京东)一个公司可能具有很多的域名,也都不是同源地址,如果在公司内部都不能进行数据请求,是很不方便的。
20.2. 同源策略
同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能。
同源策略不允许和非同源的网站之间发送ajax请求
发送跨域请求时,请求发送是成功的,响应也是成功的,只不过浏览器将响应的信息拦截了,我们无法操作。
- 对我们操作的影响,无法对非同源的地址发送ajax请求(不能跨域)
20.3. 跨域
跨域指的是非同源网站之间发送ajax请求
现在,实现跨域数据请求,最主要的两种解决方案,分别是 JSONP 和 CORS。
JSONP
兼容性好,但是只支持GET
CORS
兼容性不太好,但是支持GET、POST,并且是标准中提供的方式。
20.4. 跨域方式-JSONP
JSONP:出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。
JSONP (JSON with Padding) 是 JSON 的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。
由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。
但是
<script>
标签不受浏览器同源策略的影响,可以通过 src 属性,请求非同源的 js 脚本。
- JSONP 的实现原理:
通过
<script>
标签的 src 属性,请求跨域的数据接口,并通过函数调用的形式,接收跨域接口响应回来的数据。
同源策略不限制script标签对非同源地址进行请求
可以借助script标签进行JSONP实现
<!--
使用JSONP进行请求处理
步骤:
1 准备一个处理函数
2 通过script标签的src属性,进行接口的请求
- 因为同源策略不会限制script标签的功能
3 请求时传入请求参数
- callback 用来传递本地处理函数的函数名
- 其他参数随便写
4 当响应结束后,步骤1设置的处理函数会自动调用
- 可以在处理函数中对响应数据进行后续处理
-->
<script>
function fun(res) {
console.log(res);
}
</script>
<script src="http://ajax.frontend.itheima.net:3006/api/jsonp?callback=fun&name=jack"></script>
说明:
- JSONP和JSON没有本质关联
- JSONP与ajax没有任何关联
- JSONP是使用script标签的src属性进行请求发送
- ajax是通过浏览器提供的XMLHttpRequest对象发送请求
20.5. 跨域方式-CORS
CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。
20.6. jQuery发送JSONP请求的方式
jQuery 中的 JSONP,也是通过
<script>
标签的 src 属性实现跨域数据访问的,只不过,jQuery 采用的是动态创建和移除
<script>
标签的方式,来发起 JSONP 数据请求。
在发起 JSONP 请求的时候,动态向
<header>
中 append 一个<script>
标签;在 JSONP 请求成功以后,动态从
<header>
中移除刚才 append 进去的<script>
标签;
jQuery使用的是
$.ajax()
方法进行JSONP操作,
-
设置dataType属性为’jsonp’
-
说明:
- 可以从浏览器的network看到请求的类型为 script
- jQuery会将使用过的用于发送jsonp请求的script标签移除,打开页面也看不到
$.ajax({
type: 'GET',
url: 'http://ajax.frontend.itheima.net:3006/api/jsonp',
data: {
name: 'jack',
age: 18
},
// 下面的两个属性作为了解即可,通常不会使用
//jsonp: 'xyz', // 将默认的请求参数名callback设置为其他名称
//jsonpCallback: 'abc', // 将处理函数名称设置为指定名称
dataType: 'jsonp', // 设置这句话后,jQuery就会使用JSONP的方式进行请求发送
success: function (res) {
console.log(res);
}
});
21. 防抖和节流
21.1. 防抖
防抖策略(debounce)是当事件被触发后,延迟 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。
进行重复操作时,设置时间间隔,以最后一次满足间隔的操作为准进行执行。
简单来说:就是以满足间隔的最后一次为准执行事件
应用场景 :用户在输入框中连续输入一串字符时,可以通过防抖策略,只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源。设置防抖操作可以减少页面中不必要的请求次数
// --- 设置防抖功能
var timer = null; // 用来保存进行防抖操作的定时器id
// 设置事件
$('#ipt').on('keyup', function () {
// --- 如果再次输入,将上次的定时器清除即可
clearTimeout(timer);
// --- 通过定时器控制
timer = setTimeout(function () {
getData(val);
}, 100);
});
// 封装函数,用来进行数据请求
function getData(val) {
$.ajax({
url: 'https://suggest.taobao.com/sug',
data: { q: val },// 淘宝的这个接口指定了请求参数名为q,代表要查询的内容
dataType: 'jsonp', // 使用jsonp方式发送请求
success: function (res) {
// 3 检测数据并创建结构(封装为函数,在多个地方使用)
renderList(res);
}
});
}
21.2. 节流
节流策略(throttle),顾名思义,可以减少一段时间内事件的触发频率。
概念:也可以称为函数节流,目的是减少某些操作的触发速度
节流的应用场景 :mousemove事件 scroll等事件
鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次事件;
懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源
//让操作以指定间隔执行
//通过定时器进行设置
//在指定的时间间隔内再次触发操作会被忽略
//直到本次操作完毕,才允许执行下一次
<body>
<img src="./angel.gif" alt="" id="angel" />
<script>
// 我们希望mousemove事件执行间隔变大,至少为100ms,可以使用节流操作
var flag = true; // 默认为true代表可以执行操作
// 1 设置鼠标移动事件
$(document).on('mousemove', function (e) {
if (flag !== true) {
return;
}
flag = false; // 设置下次无法触发
setTimeout(function () {
// 2 将鼠标的横纵坐标设置给img的left和top即可
$('#angel').css({
left: e.pageX,
top: e.pageY
});
flag = true; // 本次间隔后操作执行后,允许进行下次操作
}, 20);
});
</script>
</body>
21.3. 节流和防抖的区别:
防抖是当指定间隔时间内再次触发,使用新触发的操作再次重新记时。
节流是在指定间隔时间内再次触发,新操作会被忽略。
防抖:如果事件被频繁触发,防抖能保证只有最后一次触发生效!前面 N 多次的触发都会被忽略!
节流:如果事件被频繁触发,节流能够减少事件触发的频率,因此,节流是有选择性地执行一部分事件!