AJAX
(整理于博学谷)
1. 常识性知识
1.1 网页中如何请求数据
如果要在网页中请求服务器上的数据资源,则需要用到 XMLHttpRequest 对象。
XMLHttpRequest(简称 xhr)是浏览器提供的 js 成员,通过它,可以请求服务器上的数据资源。
最简单的用法:
var xhrObj = new XMLHttpRequest()
1.2 资源的请求方式
客户端请求服务器时,请求的方式有很多种,最常见的两种请求方式分别为 get 和 post 请求。
2. jQuery中的Ajax
浏览器中提供的 XMLHttpRequest 用法比较复杂,所以 jQuery 对 XMLHttpRequest 进行了封装,提供了一系列 Ajax 相关的函数,极大地降低了 Ajax 的使用难度。
jQuery 中发起 Ajax 请求最常用的三个方法如下:
2.1 $.get()的用法
$.get(url, [data], [callback])
url: 要请求的资源地址
data: 请求资源期间要携带的参数
callback: 请求成功时的回调函数
使用 $.get() 函数发起不带参数的请求时,直接提供请求的 URL 地址和请求成功之后的回调函数即可,示例代码如下:
$.get('http://www.liulongbin.top:3006/api/getbooks', function(res) {
console.log(res)
})
使用 $.get() 函数发起带参数的请求时,示例代码如下:
$.get('http://www.liulongbin.top:3006/api/getbooks', { id: 1 }, function(res) {
console.log(res)
})
2.2 $.post()函数的用法
jQuery 中 $.post() 函数的功能单一,专门用来发起 post 请求,从而向服务器提交数据。
$.post() 函数的语法如下:
$.post(url, [data], [callback])
使用 $post() 向服务器提交数据的示例代码如下:
$.post(
'http://www.liulongbin.top:3006/api/addbook',
{ bookname: '水浒传', author: '施耐庵', publisher: '上海图书出版社' },
function(res) {
console.log(res)
}
)
2.3 $.ajax()函数的用法
相比于 $.get() 和 $.post() 函数,jQuery 中提供的 $.ajax() 函数,是一个功能比较综合的函数,它允许我们对 Ajax 请求进行更详细的配置。
$.ajax() 函数的基本语法如下:
$.ajax({
type: '',
url: '',
data: { },
success: function(res) { }
})
使用 $.ajax() 发起 GET 请求时,只需要将 type 属性的值设置为 ‘GET’ 即可:
$.ajax({
type: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks',
data: { id: 1 },
success: function(res) {
console.log(res)
}
})
使用 $.ajax() 发起 POST 请求时,只需要将 type 属性的值设置为 ‘POST’ 即可:
$.ajax({
type: 'POST',
url: 'http://www.liulongbin.top:3006/api/addbook',
data: {
bookname: '水浒传',
author: '施耐庵',
publisher: '上海图书出版社'
},
success: function(res) {
console.log(res)
}
})
3. XMLHttpRequest
XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,通过它,可以请求服务器上的数据资源。之前所学的 jQuery 中的 Ajax 函数,就是基于 xhr 对象封装出来的。
3.1 使用xhr发起GET请求
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
3.2 xhr对象的readyState属性
XMLHttpRequest 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态。每个 Ajax 请求必然处于以下状态中的一个:
3.3 使用xhr发起带参数的GET请求
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=1')
这种在 URL 地址后面拼接的参数,叫做查询字符串。
3.4 查询字符串
定义:查询字符串(URL 参数)是指在 URL 的末尾加上用于向服务器发送信息的字符串(变量)。
格式:将英文的 ? 放在URL 的末尾,然后再加上 参数=值 ,想加上多个参数的话,使用 & 符号进行分隔。以这个形式,可以将想要发送给服务器的数据添加到 URL 中。
http://www.liulongbin.top:3006/api/getbooks
http://www.liulongbin.top:3006/api/getbooks?id=1
http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记
3.5 GET请求携带参数的本质
无论使用 $.ajax(),还是使用 $.get(),又或者直接使用 xhr 对象发起 GET 请求,当需要携带参数的时候,本质上,都是直接将参数以查询字符串的形式,追加到 URL 地址的后面,发送到服务器的。
$.get('url', {name: 'zs', age: 20}, function() {})
$.get('url?name=zs&age=20', function() {})
$.ajax({ method: 'GET', url: 'url', data: {name: 'zs', age: 20}, success: function() {} })
$.ajax({ method: 'GET', url: 'url?name=zs&age=20', success: function() {} })
3.6 使用xhr发起POST请求
var xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook')
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send('bookname=水浒传&author=施耐庵&publisher=天津图书出版社')
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
4. URL编码与解码
4.1 什么是URL编码
URL 地址中,只允许出现英文相关的字母、标点符号、数字,因此,在 URL 地址中不允许出现中文字符。
如果 URL 中需要包含中文这样的字符,则必须对中文字符进行编码(转义)。
URL编码的原则:使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。
URL编码原则的通俗理解:使用英文字符去表示非英文字符。
http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记
http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=%E8%A5%BF%E6%B8%B8%E8%AE%B0
4.2 如何对URL进行编码与解码
浏览器提供了 URL 编码与解码的 API,分别是:
- lencodeURI() 编码的函数
- decodeURI() 解码的函数
encodeURI('黑马程序员')
decodeURI('%E9%BB%91%E9%A9%AC')
5. JSON
JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。例如:
var obj = {a: 'Hello', b: 'World'}
var json = '{"a": "Hello", "b": "World"}'
5.1 JSON和JS对象的互转:
要实现从 JSON 字符串转换为 JS 对象,使用 JSON.parse() 方法:
var obj = JSON.parse('{"a": "Hello", "b": "World"}')
要实现从 JS 对象转换为 JSON 字符串,使用 JSON.stringify() 方法:
var json = JSON.stringify({a: 'Hello', b: 'World'})
5.2 序列化和反序列化
把数据对象转换为字符串的过程,叫做序列化,例如:调用 JSON.stringify() 函数的操作,叫做 JSON 序列化。
把字符串转换为数据对象的过程,叫做反序列化,例如:调用 JSON.parse() 函数的操作,叫做 JSON 反序列化。
6. XMLHttpRequest Level2
旧版XMLHttpRequest的缺点
- 只支持文本数据的传输,无法用来读取和上传文件
- 传送和接收数据时,没有进度信息,只能提示有没有完成
XMLHttpRequest Level2的新功能
- 可以设置 HTTP 请求的时限
- 可以使用 FormData 对象管理表单数据
- 可以上传文件
- 可以获得数据传输的进度信息
6.1 设置HTTP请求时限
有时,Ajax 操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。新版本的 XMLHttpRequest 对象,增加了 timeout 属性,可以设置 HTTP 请求的时限:
xhr.timeout = 3000
上面的语句,将最长等待时间设为 3000 毫秒。过了这个时限,就自动停止HTTP请求。与之配套的还有一个 timeout 事件,用来指定回调函数:
xhr.ontimeout = function(event){
alert('请求超时!')
}
6.2 FormData对象管理表单数据
Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作:
var fd = new FormData()
fd.append('uname', 'zs')
fd.append('upwd', '123456')
var xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
xhr.send(fd)
FormData对象也可以用来获取网页表单的值,示例代码如下:
var form = document.querySelector('#form1')
form.addEventListener('submit', function(e) {
e.preventDefault()
var fd = new FormData(form)
var xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
xhr.send(fd)
xhr.onreadystatechange = function() {}
})
7. axios
Axios 是专注于网络数据请求的库。相比于原生的 XMLHttpRequest 对象,axios 简单易用。相比于 jQuery,axios 更加轻量化,只专注于网络数据请求。
7.1 axios发起GET请求
axios 发起 get 请求的语法:
axios.get('url', { params: { } }).then(callback)
具体的请求示例如下:
var url = 'http://www.liulongbin.top:3006/api/get'
var paramsObj = { name: 'zs', age: 20 }
axios.get(url, { params: paramsObj }).then(function(res) {
var result = res.data
console.log(res)
})
7.2 axios发起POST请求
axios 发起 post 请求的语法:
axios.post('url', { }).then(callback)
具体的请求示例如下:
var url = 'http://www.liulongbin.top:3006/api/post'
var dataObj = { location: '北京', address: '顺义' }
axios.post(url, dataObj).then(function(res) {
var result = res.data
console.log(result)
})
7.3 直接使用axios发起请求
axios 也提供了类似于 jQuery 中 $.ajax() 的函数,语法如下:
axios({
method: '请求类型',
url: '请求的URL地址',
data: { },
params: { }
}) .then(callback)
直接使用axios发起GET请求
axios({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/get',
params: {
name: 'zs',
age: 20
}
}).then(function(res) {
console.log(res.data)
})
直接使用axios发起POST请求
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/post',
data: {
bookname: '程序员的自我修养',
price: 666
}
}).then(function(res) {
console.log(res.data)
})
8. 跨域和JSONP
8.1同源
如果两个页面的协议,域名和端口都相同,则两个页面具有相同的源。
例如,下表给出了相对于 http://www.test.com/index.html 页面的同源检测:
同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能。
MDN 官方给定的概念:同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
通俗的理解:浏览器规定,A 网站的 JavaScript,不允许和非同源的网站 C 之间,进行资源的交互,例如:
- 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
- 无法接触非同源网页的 DOM
- 无法向非同源地址发送 Ajax 请求
8.2 跨域
同源指的是两个 URL 的协议、域名、端口一致,反之,则是跨域。
出现跨域的根本原因:浏览器的同源策略不允许非同源的 URL 之间进行资源的交互。
下面这两个页面跨域
网页:http://www.test.com/index.html
接口:http://www.api.com/userlist
8.3如何实现跨域数据请求
现如今,实现跨域数据请求,最主要的两种解决方案,分别是 JSONP 和 CORS。
JSONP:出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。
CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。
跨域主要是后端来解决,jsonp缺陷太大,基本上不使用。
开发小技巧:
防抖:
防抖策略(debounce)是当事件被触发后,延迟 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。
应用场景:
用户在输入框中连续输入一串字符时,可以通过防抖策略,只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源;
节流:
节流策略(throttle),顾名思义,可以减少一段时间内事件的触发频率。
①鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;
②懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源;
应用场景:
控制轮播图的速度,在京东项目中有实现。
|