network用来检测浏览器发出的每次请求以及响应内容
上面发送请求的方式,统一特点:都会出现跳转(有的是我们无法干预的)
实际页面功能制作时,很多的功能虽然请求了新的数据,但是并没有出现跳转,只是局部刷新
结论:传统的请求方式无法满足现代网页的所有功能,就需要使用新的请求方式----AJAX。
Ajax(Asynchronous Javascript And XML(异步 JavaScript 和 XML))
同步任务:
异步任务:
js的语言特性
单线程(只有一个人干活)
多线程(有好多人干活)
没有请求参数,不接收响应数据
$.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);
});
没有请求参数,不接收响应数据
$.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);
});
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()
实现的功能
// 用来将时间戳进行日期格式化的函数:
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);
表单在网页中主要负责数据采集功能。HTML中的标签,就是用于采集用户输入的信息 ,
由于标签的submit提交操作会发生跳转,用户体验很差,页面之前的状态和数据会丢失。
经常使用表单进行数据采集(用输入框等元素获取输入内容),使用ajax进行请求发送即可(提交)
form标签
表单域:input标签。。textarea。。select…
提交按钮:
<input type="submit">
<button type="submit">提交button>
标签的属性则是用来规定如何把采集到的数据发送到服务器。
在 jQuery 中,可以使用如下两种方式,监听到表单的提交事件:
$('#form1').submit(function(e) {
alert('监听到了表单的提交事件')
})
$('#form1').on('submit', function(e) {
alert('监听到了表单的提交事件')
})
在submit事件中,设置e.preventDefault()方法即可(推荐), return false也可以
$('#form1').submit(function(e) {
// 阻止表单的提交和页面的跳转
e.preventDefault()
})
$('#form1').on('submit', function(e) {
// 阻止表单的提交和页面的跳转
e.preventDefault()
})
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
进行直接发送XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,通过它,可以请求服务器上的数据资源。
jQuery 中的 Ajax 函数,就是基于 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);
}
};
位置:在xhr.open()的参数2 url后面书写参数内容
名称:参数的形式称为查询字符串
格式: ?名=值&名=值…
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);
}
};
XMLHttpRequest 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态。
每个 Ajax 请求必然处于以下状态中的一个:
值 状态 描述
0 unsent XMLHttpRequest对象已被创建,但尚未调用open()方法
1 opened open()方法已经被调用
2 headers_received send()方法已经被调用,响应头也已经被接收
3 loading 数据接收中
4 done Ajax请求完成,下载完毕
URL 地址中,只允许出现英文相关的字母、标点符号、数字,因此,在 URL 地址中不允许出现中文字符。
如果 URL 中需要包含中文这样的字符,则必须对中文字符进行编码(转义)。
URL编码的原则:使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。
URL编码原则的通俗理解:使用英文字符去表示非英文字符。
// 使用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'));
步骤:
// 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);
}
};
请求参数的书写位置不同:
post请求需要设置Content-Type
封装用来将对象转换为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函数
// 封装用来发送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如果不存在,则不进行调用,避免报错
可以设置 HTTP 请求的时限
可以使用 FormData 对象管理表单数据
可以上传文件
可以获得数据传输的进度信息
设置方式:
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);
}
};
FormData的作用:
注意点:
使用方式:
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);
}
};
}
<input type="file">
input[type="file"]
的files属性进行检测
<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上传文件的注意点
xhr.upload.onprogress 上传中实时触发事件
事件对象e的属性
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);
}
}
}
};
作用:用来对页面中的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图隐藏
}
})
})
指的是两个页面地址的 协议 域名 端口 完全一样,这两个地址就是同源的,或者称为同源地址。
同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能。
同源策略不允许和非同源的网站之间发送ajax请求
发送跨域请求时,请求发送是成功的,响应也是成功的,只不过浏览器将响应的信息拦截了,我们无法操作。
跨域指的是非同源网站之间发送ajax请求
现在,实现跨域数据请求,最主要的两种解决方案,分别是 JSONP 和 CORS。
JSONP
兼容性好,但是只支持GET
CORS
兼容性不太好,但是支持GET、POST,并且是标准中提供的方式。
JSONP:出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。
JSONP (JSON with Padding) 是 JSON 的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。
由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。
但是
标签不受浏览器同源策略的影响,可以通过 src 属性,请求非同源的 js 脚本。
通过
标签的 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>
说明:
CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。
jQuery 中的 JSONP,也是通过
标签的 src 属性实现跨域数据访问的,
只不过,jQuery 采用的是动态创建和移除
标签的方式,来发起 JSONP 数据请求。
在发起 JSONP 请求的时候,动态向
中 append 一个
标签;
在 JSONP 请求成功以后,动态从
中移除刚才 append 进去的
标签;
jQuery使用的是
$.ajax()
方法进行JSONP操作,
设置dataType属性为’jsonp’
说明:
$.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);
}
});
防抖策略(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);
}
});
}
节流策略(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>
防抖是当指定间隔时间内再次触发,使用新触发的操作再次重新记时。
节流是在指定间隔时间内再次触发,新操作会被忽略。
防抖:如果事件被频繁触发,防抖能保证只有最后一次触发生效!前面 N 多次的触发都会被忽略!
节流:如果事件被频繁触发,节流能够减少事件触发的频率,因此,节流是有选择性地执行一部分事件!