什么是ajax?
Ajax
(Asynchronous Javascript And XML)(异步js和XML),在网页中利用XMLHttpRequest
对象和服务器进行数据交互的方式,就是Ajax。
为什么学ajax?
之前所学的技术,只能把网页做得更漂亮,或添加一些动画的效果,但是,ajax能让我们轻松实现网页与服务器之间的数据交互
,ajax能够为咱们的网页和服务器之间进行数据传输
的功能。
ajax典型应用场景
用户检测
: 注册用户时,通过ajax的形式,动态检测用户名是否被占用搜索提示
: 当输入搜索关键字时,通过ajax形式,动态加载搜索提示列表数据分页显示
: 当点击页码值时,通过ajax的形式,根据页码值动态刷新表格的数据数据的增删查改
: 数据的添加、删除、修改、查询操作,都需要通过ajax的形式,来实现数据的交互
1.JQuery中的Ajax
浏览器中提供的XMLHttpRequest用法比较复杂,所以JQuery
对XMLHttpRequest进行了封装
,提供了一系列Ajax相关函数,极大的降低了ajax的使用难度。
JQuery中发起Ajax请求最常用的三个方法:
- $.get()
- $.post()
- $.ajax()
1.$.get()
JQeury中$.get()函数的功能单一,专门用来发送get请求从而将服务器上的资源请求到客户端来进行使用。
// 语法:
$.get(url,[data],[callback])
url
: string类型,表示要请求的资源地址data
: object类型,请求资源期间需要携带的参数callback
: function,请求成功时的回调函数
(1)$.get()发起不带参数的请求
$.get("http://www.xxx.top:3006/api/getbooks", function (res) {
console.log(res)
})
res
就是服务器返回的数据
(2)$.get()发起带参数的请求
$.get("http://www.xxx.top:3006/api/getbooks", { id: 1 }, function (res){
console.log(res)
})
2.$.post()
JQeury中$.post()函数的功能单一,专门用来发送post请求,从而向服务器提交数据。
// 语法:
$.post(url,[data],[callback])
$.post()发起提交数据的请求
$.post("http://www.xxx.top:3006/api/getbooks", {
bookname: "三国演义",
autor: "施耐庵",
publisher: "深圳图书出版社"
}, function (res) {
console.log(res)
})
3.$.ajax()
相比于 . g e t ( ) 和 .get()和 .get()和.post()函数,JQeury中提供的$.ajax()函数,是一个功能比较综合的函数,它允许我们对ajax请求更详细的配置。
// 语法:
$.ajax({
method: '',
url: '',
data: {},
success: function (res) {
}
})
method
:请求的方式,例如get或者posturl
:请求的url地址data
: 请求要携带的数据success
:请求成功之后的回调函
(1)$.ajax()发起get请求
$.ajax({
method: 'GET',
url: 'http://www.xxx.top:3006/api/getbooks',
data: { id: 1 },
success: function (res) {
console.log(res)
}
})
- 使用$.ajax()发起get请求时,只需要method属性的值改为’
get
’ - data是
可选参数
(2)$.ajax()发起post请求
$.ajax({
method: 'POST',
url: 'http://www.xxx.top:3006/api/getbooks',
data: {
bookname: "三国演义",
autor: "施耐庵",
publisher: "深圳图书出版社"
},
success: function (res) {
console.log(res)
}
})
- 使用$.ajax()发起post请求时,只需要method属性的值改为’
post
’
2.Ajax
XMLHttpRequest
(简称xhr
)是浏览器提供的JavaScript对象,通过它,可以请求服务器上的数据资源。
使用Ajax,我们就需要使用到XMLHttpRequest对象。
1.xhr发起get请求
(1).xhr发起不带参数的get请求
// 1.创建xhr对象
var xhr = new XMLHttpRequest()
// 2.调用open()函数
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
// 3.调用send()函数
xhr.send()
// 4.监听onreadystatechanges事件
xhr.onreadystatechanges = function () {
// 判断xhr请求状态和服务器响应状态
if (xhr.readyState === 4 && xhr.status === 200) {
// 获取服务器响应的数据
console.log(xhr.responseText)
}
}
(2).xhr发起带参数的get请求
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=1')
xhr.send()
xhr.onreadystatechanges = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
- 只需在调用open期间,为url地址
指定参数
(url地址后面拼接的参数为查询字符串
的形式)
扩展:
- 查询字符串是指在
url末尾
加上用于向服务器发送信息的字符串(变量) - 查询字符串的格式是将英文
?
放在url的末尾,然后再加上参数=值
,多个参数用&
符号分隔 - 通过查询字符串可以将想要发送给服务器的数据添加到url中
无论使用 . g e t ( ) 还是 .get()还是 .get()还是.ajax(),又或者直接使用xhr对象发起的GET请求,当需要携带参数的时候,本质上都是将参数以查询字符串的形式,追加到url地址的后面。
如:
$.ajax({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks',
data: {
id: 1,
bookname: '西游记',
},
// 等价于url:'url?id=1&..'
success: function (res) {
console.log(res)
}
})
2.xhr发起post请求
// 1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest()
// 2.调用open()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/getbooks')
// 3.设置Content-Type属性
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 4.调用send()
xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社')
// 5.监听onreadystatechanges事件
xhr.onreadystatechanges = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
- 需要在
setRequestHeader()
中设置Content-Type
属性 - 发起请求时所携带的参数放到send()中
扩展:
(1)在myAjax.js中封装自己的Ajax函数
// 定义resolveDate()来处理data参数
function resovleData(data) { // 处理data参数: 需要把data对象, 转换为查询字符串的格式
const arr = []
for (let k in data) {
const str = k + '=' + data[k]
arr.push(str)
}
return arr.join('&')
}
function myAjax(options) {
const xhr = new XMLHttpRequest()
// 把用户传过来的data参数转换为查询字符串
const qs = resovleData(options.data)
// 判断请求方式
if (options.method.toUpperCase() === 'GET') {
// 发起GET请求
xhr.open(options.method, options.url + '?' + qs)
xhr.send()
} else if (options.method.toUpperCase() === 'POST') {
// 发起POST请求
xhr.open(options.method, options.url)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send(qs)
}
xhr.onreadystatechanges = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// 把JSON字符串转换为JS对象
const result = JSON.parse(xhr.responseText)
options.success(result)
}
}
}
(2)使用自己的ajax
<script src="./myAjax.js"></script>
<script>
myAjax({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks',
data: {
id: 1
},
success: function (res) {
console.log(res)
}
})
</script>
3.url编码与解码
url地址中,只允许出现英文相关
的字母、标点符号、数字。因此在url地址中不允许出现中文字符等,如果需要url中包含中文这样的字符,则需要对中文字符进行编码(转义)
。
浏览器提供了url编码与解码的API,分别是: encodeURI()、decodeURI()。
url编码原则:
- 使用安全字符(英文字符)去表示不安全字符(非英文字符)
1.编码
encodeURI()
const str = '柳州螺蛳粉'
console.log(encodeURI(str)) // // %E6%9F%B3%E5%B7%9E%E8%9E%BA%E8%9B%B3%E7%B2%89
2.解码
decodeURI()
console.log(decodeURI('%E6%9F%B3%E5%B7%9E')) // 柳州
4.数据交换格式
数据交换格式
就是服务器端与客户端之间进行数据传输与交换格式。前端领域中两种经常提到的数据交换格式分别为XML和JSON。
1.XML
XML
(EXtensible Markup Language),即扩展标记语言
,和HTML类似。
示例:
<node>
<to>李四</to>
<from>张三</from>
<heading>通知</heading>
<body>开会</body>
</node>
- xml和html虽然都是标记语言,但是两者没有任何关系
- HTML被设计用来描述网页上的内容,是
网页内容
的载体
- XML被设计用来传输和存储数据,是
数据
的载体
xml的缺点:
- 格式臃肿,和数据无关的代码多,体积大,传输效率低
- 在javascript中解析XML比较麻烦
2.JSON
JSON
(JavaScript Object Notation),即JavaScript对象表示法。简单来说就是JavaScript对象和数组的字符串表示法,它使用文本表示一个JS对象或数组的信息,因此JSON本质上是字符串
。
作用:
- JSON是一种轻量级的文本数据交换格式,在作用上类似XML,专门用于存储和传输数据。
- 但是JSON比XML更小、更快、更易解析
(1)JSON的两种结构
对象结构
{
"name":"zs",
"age":20,
"gender":"男",
"address":null,
"hobby":["吃饭","睡觉","打游戏"]
}
key
必须是使用英文的双引号
包裹的字符串,value的数据类型可以是数组、字符串、布尔值、null、数组、对象6种类型
数组结构
[30,"java",true,null...]
- 数组结构中的数据类型可以是数字、字符串、布尔值、null,数组,对象6种类型
jSON和JS对象的关系:
JSON是JS对象的字符串表示法,它使用文本表示一个JS对象的信息,本质上是一个字符串,如
// 这是一个对象
var obj = {a:'hello',b:'world'}
// 这是一个JSON字符串,本质上就是字符串
var json = '{"a":"hello","b":"world"}'
(2)JSON和js对象的互转
JSON.parse()
const json = '{"a":"hello","b":"world"}'
const res1 = JSON.parse(json)
console.log(res1) // {a: 'hello', b: 'world'}
- JSON字符串转换为JS对象
JSON.stringify()
const obj = { a: 'hello', b: 'world', c: false }
const res2 = JSON.stringify(obj)
console.log(res2, typeof res2) // {"a":"hello","b":"world","c":false} string
- JS对象转换为JSON字符串
扩展:
序列化
: 把数据对象转换为字符串的过程,叫做序列化。- 调用JSON.stringify()函数的操作就叫JSON序列化
反序列化
: 把字符串转换为数据对象的过程,叫反序列化。- 调用JSON.parse()函数的操作就叫反序列化
JSON.parse()应用场景:
// Ajax向服务器发送请求
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
xhr.send()
xhr.onreadystatechanges = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText) // 得到的就是JSON字符串
console.log(typeof xhr.responseText) // string
// 将得到的JSON字符串转换为JS对象
const res = JSON.parse(xhr.responseText)
console.log(res)
}
}
5.XMLHttpRequest Leve2新特性
有时候,Ajax很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。新版本的XMLHttpRequest对象,新增了timeout
属性,可以设置HTTP请求的时限
。
1.设置超时时限
const xhr = new XMLHttpRequest()
// 设置超时时限(过了这个时限就自动停止HTTP请求)
xhr.timeout = 3000
xhr.ontimeout = function (e) {
alert('请求超时!')
}
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
xhr.send()
xhr.onreadystatechanges = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responeText)
}
}
- 与之配套的还有
ontimeout
事件,用来指定回调函数
2.FormData对象的使用
// 1.创建FormData()对象
const fd = new FormData()
// 2.调用append()函数,向fd中追加数据
fd.append('uname', '张三')
fd.append('age', 18)
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
// 3.直接提交FormData()对象
xhr.send(fd)
xhr.onreadystatechanges = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText))
}
}
3.使用FormData快速获取表单的数据
<form id="form1">
<input type="text" name="uname" autocomplete="off">
<input type="password" name="pswd">
<button type="submit">提交</button>
</form>
<script>
// 1.通过DOM操作,获取到form表单元素
const form = document.querySelector('#form1')
form.addEventListener('submit', function (e) {
// 阻止表单的默认提交行为
e.preventDefault()
// 2.创建FormData对象,快速获取到form表单中的数据
const fd = new FormData(form)
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
// 3.直接提交FormData()对象
xhr.send(fd)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText))
}
}
})
</script>
autocomplete
: 设置为off后,阻止表单自动填充
4.上传文件
<!-- 1.定义UI结构 -->
<input type="file" id="file1">
<button id="btnUpload">上传文件</button>
<br>
<img src="" alt="" id="img" width="800">
<script>
// 2.验证用户是否选择了文件
const button = document.querySelector('#btnUpload')
button.addEventListener('click', function () {
// 获取到用户选择的文件列表
const files = document.querySelector('#file1').files
if (files.length <= 0) { // 判断用户是否选择了文件
alert('请选择要上传的文件!')
}
// 3.向FormData中追加文件
const fd = new FormData()
fd.append('avatar', files[0])
// 4.使用xhr发起文件上传的请求
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
xhr.send(fd)
// 5.监听onreadystatechanges事件
xhr.onreadystatechanges = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText)
if (data.status === 200) {
// 上传成功
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
} else {
// 上传失败
console.log('文件上传失败!' + data.message)
}
}
}
})
</script>
files
属性是一个文件数组
监听文件上传的进度:
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) { //
// 计算出上传的进度
const uploadProgress = Math.ceil((e.loaded / e.total) * 100)
console.log(uploadProgress)
// 动态设置进度条
$("#precent").attr('style', 'width: ' + uploadProgress + '%;').html(uploadProgress + ' % ')
}
}
xhr.upload.onprogress
: 监听文件上传进度的事件e.lengthComputable
:是一个布尔值,表示当前上传的资源是否具有可计算的长度e.loaded
: 已传输的字节e.total
: 需要传输的总字节
监听上传完成事件:
xhr.upload.onload = function () {
// 移除上传中的类样式 添加上传完成的类样式
$('#precent').removeClass().addClass('progress-bar progress-bar-success')
}
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
xhr.send(fd)
xhr.upload.onload
: 监听文件上传完成的事件
5.用jquery实现文件上传
<!-- 定义UI结构 -->
<input type="file" id="file1">
<button id="btnUpload">上传文件</button>
<br>
<img src="images/loading.gif" alt="" id="loading" style="display: none;">
<script>
$(function () {
$(document).ajaxStart(function () {
$("#loading").show()
})
$(document).ajaxStop(function () {
$("#loading").hide()
})
$("#btnUpload").on('click', function () {
const files = $("#file1")[0].files
if (files.length <= 0) {
return alert('请选择要上传的文件!')
}
// 向FormDate中追加文件
const fd = new FormData()
fd.append('avatar', files[0])
// 使用Jquery发起上传文件的请求
$.ajax({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/upload/avatar',
data: fd,
// 必写, 不修改Content-Type属性,使用FormData默认的Content-Type值
contentType: false,
// 必写,不对FormData中的数据进行url编码,使用FormData数据原样发送到服务器
processData: false,
success: function (res) {
console.log(res)
}
})
})
})
</script>
-
ajaxStart(callback)
: 监听当前文档内所有的ajax请求 -
ajaxStop(callback)
: 监听当前文档内ajax结束时的请求
6.Axios
axios
是专注于网络数据请求的库,相比原生XMLHttpRequst对象,axios简单易用,相比jquery,axios更加轻量化,只专注于网络数据请求。
首先需要引入axios.js
文件
<script src="lib/axios.js"></script>
1.axios的基本使用
(1).axios发起get请求
axios.get(url,{params:参数对象}).then(callback)
// 请求地址
const url = 'http://www.liulongbin.top:3006/api/get'
// 请求的参数对象
const data = { name: '张三', age: 18 }
axios.get(url, { params: data }).then(function (res) {
// console.log(res)
console.log(res.data)
})
res.data
才是服务器响应回来的真实数据
(2).axios发起post请求
axios.post(url,参数对象).then(callback)
const url = 'http://www.liulongbin.top:3006/api/post'
const data = { address: '广西', location: '南宁' }
axios.post(url, data).then(function (res) {
console.log(res.data)
})
2.直接使用axios()发起请求
(1)axios()发起get请求
axios({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/get',
params: {
name: '张三',
age: 19
},
then: function (res) {
console.log(res.data)
}
})
- 发起
get
请求需要携带参数时使用的是parms
(2)axios()发起post请求
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/post',
data: {
address: '广西',
location: '南宁'
},
then: function (res) {
console.log(res.data)
}
})
- 发起
post
请求需要携带参数时使用的是data