1 AJAX原理——XMLHttpRequest
1.1 定义
1.2 使用步骤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 目标:使用XHLHttpRequest对象与服务器通信
// 1.创建XMLHttpRequest对象(可传参也可不传)
const xhr = new XMLHttpRequest();
// 2.配置请求方法和URL地址
xhr.open('GET', 'http://hmajax.itheima.net/api/province');
// 3.监听loadend事件,接收响应结果
xhr.addEventListener('loadend', () => {
// json数据是字符串,需要转换为对象
console.log(JSON.parse(xhr.response));
// 保存json中的list数据
const data = JSON.parse(xhr.response).list;
// 将list中的内容渲染到页面中
document.body.innerHTML = data.map(item => item).join('<br>')
})
// 4.发送请求
xhr.send();
</script>
</body>
</html>
结果:
1.2 XMLHttpRequest——查询参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 目标:使用XHR携带查询参数,展示某个省下属的城市列表
// 1.创建对象 XHR
const pname = '河北省';
const xhr = new XMLHttpRequest();
// 2.配置请求方法和URL地址
xhr.open('GET', `http://hmajax.itheima.net/api/city?pname=${pname}`);
// 3.监听loadend事件,接收响应结果
xhr.addEventListener('loadend', () => {
console.log(xhr.response);
// 因为得到的是json数据,所以需要转换为对象
const result = JSON.parse(xhr.response);
console.log(result);
})
// 4.发送请求
xhr.send();
</script>
</body>
</html>
结果:
1.2.1 案例——地区查询
将对象格式数据,转化为查询字符串 键=值&键=值
const parmasObj=new URLSearchParams({
pname,
cname
})
//`toString()` 的作用是将 `URLSearchParams` 对象转换为一个查询字符串,以便将其附加到 URL 的末尾。这是为了构造一个完整的 URL,用于发起 HTTP 请求。
const str=paramsObj.toString()
<!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>案例_地区查询</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
<style>
:root {
font-size: 15px;
}
body {
padding-top: 15px;
}
</style>
</head>
<body>
<div class="container">
<form id="editForm" class="row">
<!-- 输入省份名字 -->
<div class="mb-3 col">
<label class="form-label">省份名字</label>
<input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名称" />
</div>
<!-- 输入城市名字 -->
<div class="mb-3 col">
<label class="form-label">城市名字</label>
<input type="text" value="北京市" name="city" class="form-control city" placeholder="请输入城市名称" />
</div>
</form>
<button type="button" class="btn btn-primary sel-btn">查询</button>
<br><br>
<p>地区列表: </p>
<ul class="list-group">
<!-- 示例地区 -->
<!-- <li class="list-group-item">东城区</li> -->
</ul>
</div>
<!-- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> -->
<script>
// const obj = {
// pname: '广东省',
// cname: '广州市'
// }
// /**
// * 目标: 根据省份和城市名字, 查询对应的地区列表
// */
// // 1. 创建实例对象
// const xhr = new XMLHttpRequest();
// // 2. 调用open方法
// xhr.open('GET', `http://hmajax.itheima.net/api/area?pname=${obj.pname}&cname=${obj.cname}`);
// // 3. 监听loadend事件
// xhr.addEventListener('loadend', () => {
// const result = JSON.parse(xhr.response);
// console.log(result);
// })
// // 4. 发送请求
// xhr.send();
// 更简易的写法
// 目标:点击按钮,查询对应的地区列表
// 1.点击事件注册
document.querySelector('.sel-btn').addEventListener('click', () => {
// 2. 获取省份和城市名字
const pname = document.querySelector('[name="province"]').value;
const cname = document.querySelector('[name="city"]').value;
console.log(pname, cname);
// 传一个对象,会返回一个实例对象
// 得到目标格式需要使用tostring方法
const parmasObj = new URLSearchParams({
pname,
cname
});
console.log(parmasObj.toString());
// 3. 发送请求
const xhr = new XMLHttpRequest();
xhr.open('GET', `http://hmajax.itheima.net/api/area?${parmasObj.toString()}`);
xhr.addEventListener('loadend', () => {
const result = JSON.parse(xhr.response);
document.querySelector('.list-group').innerHTML = JSON.parse(xhr.response).map(item => {
return `<li class="list-group-item">${item}</li>`
}).join('')
})
// 4. 发送请求
xhr.send();
})
// 5.渲染页面
</script>
</body>
</html>
1.3 XMLHttpRequest——数据提交
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="reg-btn">注册用户</button>
</body>
<script>
document.querySelector('.reg-btn').addEventListener('click', () => {
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://hmajax.itheima.net/api/register')
xhr.addEventListener('loadend', () => {
console.log(xhr.response);
})
// 设置请求头
//1.设置请求头数据类型 (根据接口文档设置)
xhr.setRequestHeader('Content-Type', 'application/json')
//2.在send方法中携带参数
const obj = {
username: 'csqsdc',
password: '1234554646',
}
// 将obj对象转换为json字符串
const data = JSON.stringify(obj)
xhr.send(data)//请求体参数携带在send方法中
})
</script>
</html>
结果:
2 Promise
2.1 语法
<!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管理异步任务
*/
// 1.创建Promise对象
const p = new Promise(function (resolve, reject) {
// 2.执行异步任务
//如果成功,则调用resolve方法
resolve('成功')//相当于调用then的回调函数
//如果失败,则调用reject方法
reject('失败')//相当于调用catch的回调函数
// 3.接收成功或者失败的结果
p.then(function (res) { console.log(res) })//实参,它的形参是resolve
.catch(function (err) { console.log(err) })//实参,它的形参是reject
})
</script>
</body>
</html>
2.2 promise的三种状态
Promise存在状态凝固特性,一旦状态从(pending)修改为fulfilled或者是rejected后就不会再次修改了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 1.创建Promise对象
const p = new Promise((resolve, reject) => {
// 2.执行异步任务
setTimeout(() => {
// 3.根据条件执行resolve或reject
resolve(new Errorr('模拟AJAX请求——失败结果'))
}, 2000)
})
console.log(p)
//(1). 待定(pending)状态:创建了Promise对象,但还没有调用resolve或reject
//(2). 成功(fulfilled)状态:调用resolve方法
//(3). 失败(rejected)状态:调用reject方法
// 2.执行异步任务
p.then(result => {
console.log(result)
}).catch(err => {
console.log(err)
})
</script>
</body>
</html>
3.案例——使用promise和XHR获取省份列表
<!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+XHR_获取省份列表</title>
</head>
<body>
<p class="my-p"></p>
<script>
/**
* 目标:使用Promise管理XHR请求省份列表
*
* 1. 创建Promise对象
*
* 2. 执行XHR异步代码,获取省份列表
* 3. 关联成功或失败函数,做后续处理
*/
// 1. 创建Promise对象
const p = new Promise(function (resolve, reject) {
// 2.执行XHR异步代码,获取省份列表
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://hmajax.itheima.net/api/province')
xhr.addEventListener('loaded', () => {
if (xhr.status == 200) {
}
})
// 发送请求
xhr.send();
})
// 使用promise在函数外面获取结果
p.then(res => {
const p = document.querySelector('.my-p')
p.innerHTML = JSON.parse(res).list.map(item => item).join('<br>')
console.log(JSON.parse(res).list)
})
</script>
</body>
</html>
结果:
3 封装简易版 axios
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
<!-- 1. 定义myAxios函数,接收配置对象,返回Promise对象 -->
function myAxios(option) {
// 解构配置对象
const { url, method } = option
// 两个参数,一个成功,一个失败
// 回调函数
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url)
xhr.addEventListener('loaded', () => {
// console.log(xhr.response)
resolve(xhr.response)
})
xhr.send()
})
}
// 2. 调用myAxios函数,传入配置对象
myAxios({
url: 'https://hmajax.itheima.net/api/province',
method: 'GET',
}).then(res=>{
console.log(res)
})
</script>
</body>
</html>
3.1 封装简易axios函数,获取地区列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// <!-- 1. 定义myAxios函数,接收配置对象,返回Promise对象 -->
function myAxios(option) {
// 解构配置对象
let { url, method, parmas } = option
// console.log(parmas)
// 判断parmas是否存在(使用tostring将对象转化为字符串)
parmas = parmas ? new URLSearchParams(parmas).toString : ''
// 拼接URl地址
parmas ? url + '?' + parmas : url
// 两个参数,一个成功,一个失败
// 回调函数
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url)
xhr.addEventListener('loaded', () => {
// console.log(xhr.response)
resolve(JSON.parse(xhr.response))
})
xhr.send()
})
}
myAxios({
url: 'http://hmajax.itheima.net/api/area',
method: 'GET',
parmas: {
pname: '河北省',
cname: '邯郸市'
}
// then方法打印出响应数据
}).then(res => {
document.querySelector('.my-p').innerHTML = res.list.map(item => item).join('<br>')
})
</script>
</body>
</html>
3.2 封装_简易axios_注册用户
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>click me</button>
<script>
// const btn = document.querySelector('button')
// <!-- 1. 定义myAxios函数,接收配置对象,返回Promise对象 -->
function myAxios(option) {
// 解构配置对象
let { url, method, params, data } = option
// 判断params是否存在
params = params ? new URLSearchParams(params).toString() : ''
// 拼接URL地址
url = params ? url + '?' + params : url
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url)
// 设置请求头
if (data) {
xhr.setRequestHeader('Content-Type', 'application/json')
// 处理数据
data = JSON.stringify(data)
}
xhr.addEventListener('load', () => {
resolve(JSON.parse(xhr.response))
})
xhr.send(data)
})
}
document.querySelector('button').addEventListener('click', () => {
myAxios({
url: 'http://ajax-api.itheima.net/register',
method: 'POST',
data: {
username: 'csqqqq',
password: '123456'
}
}).then(res => {
console.log(res)
}).catch(error => {
console.error('请求失败:', error)
})
})
</script>
</body>
</html>
结果