一、XMLHttpRequest
XMLHttpRequest (XHR)对象用于与服务器交互,通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。 XMLHttpRequest 在AJAX 编程中被大量使用。
关系:axios 内部采用 XMLHttpRequest 与服务器交互
好处:掌握使用 XHR 与服务器进行数据交互,了解 axios 内部原理
1.2 使用 XMLHttpRequest步骤
(1)创建 XMLHttpRequest 对象
(2)配置请求方法和请求
(3)url 地址 监听 loadend 事件
(4)接收响应结果 发起请求
代码展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XMLHttpRequest_基础使用</title>
</head>
<body>
<p></p>
<script>
/**
* 目标:使用XMLHttpRequest对象与服务器通信
* 1. 创建 XMLHttpRequest 对象
* 2. 配置请求方法和请求 url 地址
* 3. 监听 loadend 事件,接收响应结果
* 4. 发起请求
* get http://hmajax.itheima.net/api/province
*/
// 1. 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest()
// 2. 配置请求方法和请求 url 地址
xhr.open('get', 'http://hmajax.itheima.net/api/province')
// 3. 监听 loadend 事件,接收响应结果
xhr.addEventListener('loadend', () => {
const res = JSON.parse(xhr.response)
console.log(res)
document.querySelector('p').innerHTML = res.list.join('<br>')
})
// 4. 发起请求
xhr.send()
</script>
</body>
</html>
1.3 XMLHttpRequest - 查询参数
定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据 语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
代码展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XMLHttpRequest_查询参数</title>
</head>
<body>
<p></p>
<script>
/**
* 目标:使用XHR携带查询参数,展示某个省下属的城市列表
* get http://hmajax.itheima.net/api/city
* 请求参数(查询参数): pname
* 查询参数都是在 url 后面使用 ? 拼接
* ?参数名1=参数值1&参数名2=参数值2
*/
// 1. 创建 xhr
const xhr = new XMLHttpRequest()
// 2. 设置请求方法和 url
xhr.open('get', 'http://hmajax.itheima.net/api/city?pname=湖北省')
// 3. 添加事件监听 loadend
xhr.addEventListener('loadend', () => {
const res = JSON.parse(xhr.response)
console.log(res)
document.querySelector('p').innerHTML = res.list.join('<br>')
})
// 4. 发送请求
xhr.send()
</script>
</body>
</html>
1.4 XMLHttpRequest - 数据提交
需求:通过 XHR 提交用户名和密码,完成注册功能
核心: 请求头设置 Content-Type:application/json 请求体携带 JSON 字符串
代码展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XMLHttpRequest_数据提交</title>
</head>
<body>
<button class="reg-btn">注册用户</button>
<script>
/**
* 目标:使用xhr进行数据提交-完成注册功能
* POST http://hmajax.itheima.net/api/register
* Body 参数(application/json)
* username
* password
*/
document.querySelector('.reg-btn').addEventListener('click', () => {
// 1. 创建 xhr 对象
const xhr = new XMLHttpRequest()
// 2. 设置请求方法和 url
xhr.open('post', 'http://hmajax.itheima.net/api/register')
// 3. 监听 loadend 事件获取响应
xhr.addEventListener('loadend', () => {
const res = JSON.parse(xhr.response)
console.log(res)
})
// 4. 设置请求头
// 参数1: 键
// 参数2: 值
xhr.setRequestHeader('Content-Type', 'application/json')
// 5. 发请求 -> 携带参数
const user = {
username: 'mrdrager123',
password: '123456'
}
xhr.send(JSON.stringify(user))
})
</script>
</body>
</html>
二、Promise
1.Promise 对象用于表示一个异步操作的最终完成(或失败) 及其结果值
2.好处:
逻辑更清晰
了解 axios 函数内部运作机制
能解决回调函数地狱问题
3.一个Promise对象,必然处于以下几种状态之一
待定(pending) :初始状态,既没有被兑现,也没有被拒绝
已兑现(fulfilled) :意味着,操作成功完成
已拒绝(rejected) :意味着,操作失败
4.注意:Promise对象一旦被兑现/拒绝 就是已敲定了,状态无法再被改变
代码展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>认识Promise</title>
</head>
<body>
<script>
/**
* 目标:使用 Promise 管理异步任务
* 用定时器来模拟请求
*/
// Promise 对象是帮助我们完成异步任务的, 所有的异步任务都会有成功或失败的结果
// 可以通过 Promise 对象的 .then 方法获取成功的结果 .catch 获取失败的结果
// 1. 创建 Promise 对象
// 参数: 回调函数, 会立即执行
const p = new Promise((resolve, reject) => {
// console.log('我会立即执行')
// 在回调函数中, 可以执行异步任务 (定时器 / AJAX)
// 回调函数中有两个参数:
// 参数1: resolve 成功的回调
// 参数2: reject 失败的回调
setTimeout(() => {
// console.log('模拟 AJAX 请求结果 - 成功')
// resolve('模拟 AJAX 请求结果 - 成功')
reject('模拟 AJAX 请求 - 失败')
}, 3000)
})
p.then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
</script>
</body>
</html>
三、封装简易版 axios
案例展示1:
需求:基于 Promise + XHR 封装 myAxios 函数,获取省份列表展示
步骤: 定义 myAxios 函数,
(1)接收配置对象,返回 Promise 对象
(2)发起 XHR 请求,默认请求方法为 GET
(3)调用成功/失败的处理程序
(4)使用 myAxios 函数,获取省份列表展示
代码展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>封装_简易axios函数_获取省份列表</title>
</head>
<body>
<p></p>
<script>
/**
* 目标:封装_简易axios函数_获取省份列表
* 1. 定义myAxios函数,接收配置对象,返回Promise对象
* 2. 发起XHR请求,默认请求方法为GET
* 3. 调用成功/失败的处理程序
* 4. 使用myAxios函数,获取省份列表展示
*/
/**
* 参数1: config 配置对象
* */
// 1. 定义myAxios函数,接收配置对象,返回Promise对象
function myAxios(config) {
return new Promise((resolve, reject) => {
// 2. 发起XHR请求,默认请求方法为GET
const xhr = new XMLHttpRequest()
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
// 传递成功的结果
resolve(JSON.parse(xhr.response))
} else {
// 传递失败的结果
reject(new Error(xhr.response))
}
})
xhr.send()
})
}
myAxios({
url: 'http://hmajax.itheima.net/api/province'
}).then(res => {
console.log(res)
document.querySelector('p').innerHTML = res.list.join('<br>')
}).catch(e => {
console.log(e.message)
document.querySelector('p').innerHTML = e.message
})
</script>
</body>
</html>
案例展示2:
需求:修改 myAxios 函数支持传递查询参数,获取"辽宁省","大连市"对应地区列表展示
步骤:
(1)myAxios 函数调用后,判断 params 选项
(2)基于 URLSearchParams 转换查询参数字符串
(3)使用自己封装的 myAxios 函数展示地区列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>封装_简易axios函数_获取地区列表</title>
</head>
<body>
<p class="my-p"></p>
<script>
/**
* 目标:封装_简易axios函数_获取地区列表
* 1. 判断有params选项,携带查询参数
* 2. 使用URLSearchParams转换,并携带到url上
* 3. 使用myAxios函数,获取地区列表
*/
function myAxios(config) {
return new Promise((resolve, reject) => {
// 1. 判断有没有传入 params 参数
if (config.params) {
// 2. 如果有 params 需要将其转换成查询参数字符串: xxx=xxx&aaa=aaa
const obj = new URLSearchParams(config.params)
// console.log( obj.toString() )
// 3. 将参数字符串拼接到 url 后面
config.url += `?${obj.toString()}`
}
const xhr = new XMLHttpRequest()
// 要在设置请求方法和 url 之前对查询参数进行处理
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
// 传递成功的结果
resolve(JSON.parse(xhr.response))
} else {
// 传递失败的结果
reject(new Error(xhr.response))
}
})
xhr.send()
})
}
myAxios({
url: 'http://hmajax.itheima.net/api/area',
params: {
pname: '湖北省',
cname: '武汉市'
}
}).then(res => {
console.log(res)
})
</script>
</body>
</html>
案例展示3:
需求:修改 myAxios 函数支持传递请求体数据,完成注册用户功能
步骤:
(1)myAxios 函数调用后,判断 data 选项 转换数据类型,
(2)在 send 方法中发送 使
(3)用自己封装的 myAxios 函数完成注册用户功能
代码展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>封装_简易axios函数_注册用户</title>
</head>
<body>
<button class="reg-btn">注册用户</button>
<script>
/**
* 目标:封装_简易axios函数_注册用户
* 1. 判断有data选项,携带请求体
* 2. 转换数据类型,在send中发送
* 3. 使用myAxios函数,完成注册用户
* 查询字符串: 参数=参数值&参数2=参数值
* 请求体参数字符串:
* 1. 设置请求头: Content-Type: application/json
* 2. 请求体携带: JSON 字符串
*/
function myAxios(config) {
return new Promise((resolve, reject) => {
if (config.params) {
const obj = new URLSearchParams(config.params)
config.url += `?${obj.toString()}`
}
const xhr = new XMLHttpRequest()
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
if (config.data) {
// 1. 设置请求头: Content-Type: application/json
xhr.setRequestHeader('Content-Type', 'application/json')
// 2. 请求体携带: JSON 字符串
xhr.send(JSON.stringify(config.data))
} else {
xhr.send()
}
})
}
document.querySelector('.reg-btn').addEventListener('click', () => {
myAxios({
url: 'http://hmajax.itheima.net/api/register',
method: 'post',
data: {
username: 'xiaochun',
password: '123456'
}
}).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
})
</script>
</body>
</html>
四、URLSearchParams
1.URLSearchParams 对象专门用于处理url网址信息中的查询字符串,在网址字符串中通常都是 ? 问号之后的内容(不包含问号)。
在URL对象中也有一个属性 searchParams 返回该对象,会对查询字符串做解析处理,以等号分割生成对应的 key-value 键值对的数据形式。
2.URLSearchParams实例方法
URLSearchParams
对象提供了多个实例方法,用于读取或修改查询字符串数据,还提供了三个方法用来对数据进行遍历。