◆ XMLHttpRequest
-
什么是XMLHttpRequest?
定义:
关系:axios 内部采用 XMLHttpRequest 与服务器交互
注意:直白点说就是axios内部就是封装了XMLHttpRequest这个对象来实现发送异步请求的
-
使用 XMLHttpRequest
步骤:
1. 创建 XMLHttpRequest 对象
2. 配置请求方法和请求 url 地址
3. 监听 loadend 事件,接收响应结果
4. 发起请求
1.无参数的情况
获取并展示所有省份名字
//1. 创建 XMLHttpRequest 对象const xhr = new XMLHttpRequest()//2. 配置请求方法和请求 url 地址xhr.open('GET','http://hmajax.itheima.net/api/province')//3. 监听 loadend 事件,接收响应结果xhr.addEventListener('loadend',function(){console.log(xhr.response);const rs = JSON.parse(xhr.response)console.log(rs.list.join('<br>'));document.querySelector('p').innerHTML = rs.list.join('<br>')})//4. 发起请求xhr.send()
2.有URL查询参数的情况
- 使用字符串拼接
- 使用浏览器提供的内置对对象 URLSearchParams
// 1. 组织查询参数字符串const qObj = {pname: '辽宁省',cname: '大连市'}// 2查询参数对象 -> 查询参数字符串const paramsObj = new URLSearchParams(qObj)const queryString = paramsObj.toString()console.log(queryString)// 3. 使用XHR对象,查询地区列表const xhr = new XMLHttpRequest()xhr.open('GET', `http://hmajax.itheima.net/api/area?${queryString}`)xhr.addEventListener('loadend', () => {console.log(xhr.response)const data = JSON.parse(xhr.response)console.log(data)const htmlStr = data.list.map(areaName => {return `<li class="list-group-item">${areaName}</li>`}).join('')console.log(htmlStr)})xhr.send()
3.以请求体(JSON)的方式发送数据的情况
需求:通过 XHR 提交用户名和密码,完成注册功能
核心:
请求头设置 Content-Type:application/json
请求体携带 JSON 字符串
/*** 目标:使用xhr进行数据提交-完成注册功能*/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)})// 设置请求头-告诉服务器内容类型(JSON字符串)xhr.setRequestHeader('Content-Type', 'application/json')// 准备提交的数据const userObj = {username: 'itheima007',password: '7654321'}//将对象转化成JSON字符串const userStr = JSON.stringify(userObj)// 设置请求体,发起请求xhr.send(userStr)})
总结:
. AJAX 原理是什么?
- ➢ XMLHttpRequest 对象
2. 为什么学习 XHR?
- ➢ 有更多与服务器数据通信方式
- ➢ 了解 axios 内部原理
3. XHR 使用步骤?
- ➢ 创建 XHR 对象
- ➢ 调用 open 方法,设置 url 和请求方法
- ➢ 监听 loadend 事件,接收结果
- ➢ 调用 send 方法,发起请求
4.上传图片等二进制的情况
//4 上传图片等二进制的情况//1. 获取图片文件document.querySelector('.upload').addEventListener('change',(e)=>{// console.log(e.target.files); //2. 使用 FormData 携带图片文件const fd = new FormData()// append() 追加元素fd.append('img',e.target.files[0])//3 使用XmlHttpRequest提交数据const xhr = new XMLHttpRequest()//设置方法和urlxhr.open('POST','http://hmajax.itheima.net/api/uploadimg')//设置回调函数xhr.addEventListener('loadend',function(){console.log(xhr.response); //这里不是一个对象,是字符串 console.log(JSON.parse(xhr.response));document.querySelector('img').src = JSON.parse(xhr.response).data.url})xhr.send(fd)})
◆ Promise
什么是 Promise?
- 表示(管理)一个异步操作最终状态和结果值的对象
定义:
Promise 使用步骤
Promise - 三种状态
概念:一个Promise对象,必然处于以下几种状态之一
- 待定(pending) :初始状态,既没有被兑现,也没有被拒绝
- 已兑现(fulfilled) :意味着,操作成功完成
- 已拒绝(rejected) :意味着,操作失败
注意: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+XHR_获取省份列表</title>
</head><body><p class="my-p"></p><script>/*** 目标:使用Promise管理XHR请求省份列表* 1. 创建Promise对象* 2. 执行XHR异步代码,获取省份列表* 3. 关联成功或失败函数,做后续处理*/// 1. 创建Promise对象const p = new Promise((resolve, reject) => {// 2. 执行XHR异步代码,获取省份列表const xhr = new XMLHttpRequest()xhr.open('GET', 'http://hmajax.itheima.net/api/province')xhr.addEventListener('loadend', () => {// xhr如何判断响应成功还是失败的?// 2xx开头的都是成功响应状态码if (xhr.status >= 200 && xhr.status < 300) {resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})xhr.send()})// 3. 关联成功或失败函数,做后续处理p.then(result => {console.log(result)document.querySelector('.my-p').innerHTML = result.list.join('<br>')}).catch(error => {// 错误对象要用console.dir详细打印console.dir(error)// 服务器返回错误提示消息,插入到p标签显示document.querySelector('.my-p').innerHTML = error.message})</script>
</body></html>
总结
◆ 封装简易版 axios
function myAxios(config) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest()if (config.params) {const paramsObj = new URLSearchParams(config.params)const queryString = paramsObj.toString()config.url += `?${queryString}`}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) {const jsonStr = JSON.stringify(config.data)xhr.setRequestHeader('Content-Type', 'application/json')xhr.send(jsonStr)} else {xhr.send()}})
}
◆ 案例 - 天气预报
步骤:
1. 获取北京市天气数据,展示
2. 搜索城市列表,展示
3. 点击城市,显示对应天气数据
<!DOCTYPE html>
<html lang="zh-CN"><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"><link rel="stylesheet" href="./css/reset.css"><link rel="stylesheet" href="./css/index.css"><title>案例_天气预报</title>
</head><body><div class="container"><!-- 顶部 --><div class="top-box"><div class="title"><span class="dateShort">10月28日</span><span class="calendar">农历 <span class="dateLunar">十月初四</span></span></div><div class="search-box"><div class="location"><img src="./imgs/定位.png" alt=""><span class="area">城市名</span></div><!-- 搜索框+搜索列表 --><div class="search"><input type="text" class="search-city" placeholder="搜索城市"><ul class="search-list"><li class="city-item">北京市</li></ul></div></div></div><!-- 当前天气 --><div class="weather-box"><div class="tem-box"><span class="temp"><span class="temperature">12</span><span>°</span></span></div><div class="climate-box"><div class="air"><span class="psPm25">55</span><span class="psPm25Level">良</span></div><ul class="weather-list"><li><img src="./imgs/小雨-line.png" class="weatherImg" alt=""><span class="weather">多云</span></li><li class="windDirection">东南风</li><li class="windPower">2级</li></ul></div></div><div class="today-weather"><div class="range-box"><span>今天:</span><span class="range"><span class="weather">晴</span><span class="temNight">9</span><span>-</span><span class="temDay">14</span><span>℃</span></span></div><ul class="sun-list"><li><span>紫外线</span><span class="ultraviolet">强</span></li><li><span>湿度</span><span class="humidity">53</span>%</li><li><span>日出</span><span class="sunriseTime">06:38</span></li><li><span>日落</span><span class="sunsetTime">17:18</span></li></ul></div><!-- 周天气预报 --><div class="week-weather-box"><div class="title">7日内天气预报</div><ul class="week-wrap"><li class="item"><div class="date-box"><span class="dateFormat">今天</span><span class="date">10月28日</span></div><img src="./imgs/多云.png" alt="" class="weatherImg"><span class="weather">多云</span><div class="temp"><span class="temNight">12</span>-<span class="temDay">12</span><span>℃</span></div><div class="wind"><span class="windDirection">东南风</span><span class="windPower"><3级</span></div></li><li class="item"><div class="date-box"><span class="dateFormat">今天</span><span class="date">10月28日</span></div><img src="./imgs/多云.png" alt="" class="weatherImg"><span class="weather">多云</span><div class="temp"><span class="temDay">12</span>-<span class="temNight">12</span><span>℃</span></div><div class="wind"><span class="windDirection">东南风</span><span class="windPower"><3级</span></div></li><li class="item"><div class="date-box"><span class="dateFormat">今天</span><span class="date">10月28日</span></div><img src="./imgs/多云.png" alt="" class="weatherImg"><span class="weather">多云</span><div class="temp"><span class="temDay">12</span>-<span class="temNight">12</span><span>℃</span></div><div class="wind"><span class="windDirection">东南风</span><span class="windPower"><3级</span></div></li><li class="item"><div class="date-box"><span class="dateFormat">今天</span><span class="date">10月28日</span></div><img src="./imgs/多云.png" alt="" class="weatherImg"><span class="weather">多云</span><div class="temp"><span class="temDay">12</span>-<span class="temNight">12</span><span>℃</span></div><div class="wind"><span class="windDirection">东南风</span><span class="windPower"><3级</span></div></li><li class="item"><div class="date-box"><span class="dateFormat">今天</span><span class="date">10月28日</span></div><img src="./imgs/多云.png" alt="" class="weatherImg"><span class="weather">多云</span><div class="temp"><span class="temDay">12</span>-<span class="temNight">12</span><span>℃</span></div><div class="wind"><span class="windDirection">东南风</span><span class="windPower"><3级</span></div></li><li class="item"><div class="date-box"><span class="dateFormat">今天</span><span class="date">10月28日</span></div><img src="./imgs/多云.png" alt="" class="weatherImg"><span class="weather">多云</span><div class="temp"><span class="temDay">12</span>-<span class="temNight">12</span><span>℃</span></div><div class="wind"><span class="windDirection">东南风</span><span class="windPower"><3级</span></div></li><li class="item"><div class="date-box"><span class="dateFormat">今天</span><span class="date">10月28日</span></div><img src="./imgs/多云.png" alt="" class="weatherImg"><span class="weather">多云</span><div class="temp"><span class="temDay">12</span>-<span class="temNight">12</span><span>℃</span></div><div class="wind"><span class="windDirection">东南风</span><span class="windPower"><3级</span></div></li></ul></div></div><!-- 自己封装myAxios函数 --><script src="./js/my-axios.js"></script><!-- 搜索框+下拉菜单出现逻辑 --><script src="./js/search.js"></script><!-- 核心js --><script src="./js/index.js"></script><script>//1 获取默认城市的天气预报function getWeather(cityCode){myAxios({url: 'http://hmajax.itheima.net/api/weather',params: {city: cityCode}}).then(result=>{//渲染数据console.log(result);const wObj = result.data//更新城市名document.querySelector('.area').innerHTML = result.data.area//当前日期document.querySelector('.title').innerHTML = `<span class="dateShort">${wObj.dateShort}</span><span class="calendar">农历 <span class="dateLunar">${wObj.dateLunar}</span></span>`//当前气候document.querySelector('.climate-box').innerHTML = `<div class="air"><span class="psPm25">${wObj.psPm25}</span><span class="psPm25Level">${wObj.psPm25Level}</span></div><ul class="weather-list"><li><img src=${wObj.weatherImg} class="weatherImg" alt=""><span class="weather">${wObj.weather}</span></li><li class="windDirection">${wObj.windDirection}</li><li class="windPower">${wObj.windPower}</li></ul> `//当前温度document.querySelector('.tem-box').innerHTML = `<span class="temp"><span class="temperature">${wObj.temperature}</span><span>°</span></span>`const todayWeather = wObj.todayWeatherdocument.querySelector('.today-weather').innerHTML = `<div class="range-box"><span>今天:</span><span class="range"><span class="weather">${todayWeather.weather}</span><span class="temNight">${todayWeather.temNight}</span><span>-</span><span class="temDay">${todayWeather.temDay}</span><span>℃</span></span></div><ul class="sun-list"><li><span>紫外线</span><span class="ultraviolet">${todayWeather.ultraviolet}</span></li><li><span>湿度</span><span class="humidity">${todayWeather.humidity}</span>%</li><li><span>日出</span><span class="sunriseTime">${todayWeather.sunriseTime}</span></li><li><span>日落</span><span class="sunsetTime">${todayWeather.sunsetTime}</span></li></ul>`// <!-- 周天气预报 -->document.querySelector('.week-wrap').innerHTML = wObj.dayForecast.map((item)=>`<li class="item"><div class="date-box"><span class="dateFormat">${item.dateFormat}</span><span class="date">${item.date}</span></div><img src=${item.weatherImg} alt="" class="weatherImg"><span class="weather">多云</span><div class="temp"><span class="temNight">${item.temNight}</span>-<span class="temDay">${item.temDay}</span><span>℃</span></div><div class="wind"><span class="windDirection">${item.windDirection}</span><span class="windPower">${item.windPower}</span></div></li>`).join('')})}getWeather('450700')//2 搜索城市列表document.querySelector('.search-city').addEventListener('input',function(e){//得到输入的内容const value = e.target.value// console.log(value);// 使用ajax调用接口myAxios({url: 'http://hmajax.itheima.net/api/weather/city',params: {city: value}}).then(result=>{// console.log(result);document.querySelector('.search-list').innerHTML = result.data.map(item=>`<li class="city-item" data-code="${item.code}">${item.name}</li>`)})})//使用事件委托,给每个搜索出来的li加点击事件document.querySelector('.search-list').addEventListener('click',function(e){if(e.target.classList.contains('city-item')){// console.log(222);//获取自定义属性let code = e.target.dataset.code//调用天气函数console.log(code);getWeather(code)}})</script>
</body></html>