url
统一资源定位符
协议://域名/资源路径
从服务器获取数据
案例:根据输入省份城市名字查询市区
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
function fn(){
let pName=document.querySelector('#province').value
let cName=document.querySelector('#city').value
axios({
url:'http://hmajax.itheima.net/api/area',
method:'get'//可省略
params:{
pname:pName,
cname:cName
}
}).then(result=>{
let list=result.data.list.join('</br>')
document.querySelector('div .qu').innerHTML=list
})
}
let btn=document.querySelector('.btn')
btn.addEventListener('click',fn)
</script>
补充:ES6简写,当属性名和变量名一样时
params:{
pname:pName,
cname:cName
}
可简写为
params:{
pname,
cname
}
把数据提交给服务器
-
GET获取数据
-
POST提交数据
-
PUT修改数据(全部)
PUT表示向服务器上传一个资源,并覆盖原有的资源。如果服务器中不存在该资源,则会创建一个新的资源。PUT方式的请求具有幂等性,即多次请求同一资源所产生的结果相同。
POST表示向服务器提交一份数据,服务器根据数据来进行处理。POST方式的请求没有幂等性,即同一请求会产生不同的结果。
因此,PUT适用于更新资源的操作,而POST适用于创建资源或进行一些较为复杂的操作。
-
DELETE删除数据
-
PATCH修改数据(部分)
axios请求配置
url:请求URL网址
method:请求的方法,GET可以省略
data:提交数据
例:通过axios提交用户名和密码,完成注册功能
<button class="btn">注册</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
document.querySelector('.btn').addEventListener('click',()=>{
axios({
url:'http://hmajax.itheima.net/api/register',
method:'post',
data:{
username:'aabbccdd',
password:'7654321'
}//data中如果是个对象,就会把对象转换为JSON字符串
}).then(result=>{
console.log(result)
})
})
</script>
axios错误处理
如上案例,再次注册相同的账号,会遇到报错信息
处理:用更直观的方式,给用户展示错误信息
在then后面
then(result=>{
console.log(result)
}).catch(error=>{
alert(error.response.data.message)
})
HTTP请求报文
请求行
请求头
空行
请求体
查看步骤:1.找到网络(Network)
2.Fetch/XHR
3.标头(Headers),载荷(Preview)
请求报文错误排除
HTTP响应报文
接口文档
描述接口的文章
接口:使用AJAX和服务器通讯时,使用的URL,请求方法,以及参数
登陆案例:
用户名:<input type="text" class="yhm">
密码:<input type="text" class="mm"><br>
<button class="btn">登录</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
document.querySelector('.btn').addEventListener('click',()=>{
let yhm=document.querySelector('.yhm').value
let mm=document.querySelector('.mm').value
if(yhm.length<8){
alert("用户名必须大于等于8位")
}
if(mm.length<7){
alert("密码必须大于等于7位")
}
else{
axios({
url:'http://hmajax.itheima.net/api/login',
method:'post',
data:{
username:yhm,
password:mm
}
}).then(result=>{
alert(result.data.message)
}).catch(error=>{
alert(error.response.data.message)
})
}
})
</script>
form-serialize插件
快速收集表单元素的值
例:注意input一定要有name
<form action="javascript:;" class="example-form">
<input type="text" name="uname">
<br>
<input type="text"name="pwd">
<br>
<input type="button" class="btn" value="提交">
</form>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="../node_modules/form-serialize/index.js"></script>
<script>
//使用serialize函数,快速收集表单元素的值
//参数一:要获取哪个表单的数据
document.querySelector('.btn').addEventListener('click',()=>{
const form=document.querySelector('.example-form')
const data=serialize(form,{hash:true,empty:true})
//hash:设置获取到的数据结构(true:JS对象(推荐),false:查询字符串) empty:设置是否获取空值
console.log(data)
})
</script>
Bootstrap弹框
弹框编辑姓名案例
<button type="button" class="btn btn-primary edit-btn">
编辑姓名
</button>
<div class="modal my-box" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content"><!--弹框主体-->
<div class="modal-header">
<h5 class="modal-title">请输入姓名</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<span>姓名:</span><input type="text" class="username">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary save-btn">保存</button>
</div>
</div>
</div>
</div>
<script>
const modalDom = document.querySelector('.my-box')//创建弹框对象
const modal=new bootstrap.Modal(modalDom)
//编辑姓名->点击->赋予默认姓名->弹框显示
document.querySelector('.edit-btn').addEventListener('click',()=>{
document.querySelector('.username').value='默认姓名'
modal.show()
})
//保存->点击->获取姓名->隐藏
document.querySelector('.save-btn').addEventListener('click',()=>{
const username=document.querySelector('.username').value
console.log(username)
modal.hide()
})
</script>
图片上传
<input type="file" class="upload">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
document.querySelector('.upload').addEventListener('change',e=>{
const fd=new FormData()
fd.append('img',e.target.files[0])
axios({
url:'http://hmajax.itheima.net/api/uploadimg',
method:'POST',
data:fd
}).then(result=>{
console.log(result)
})
})
</script>
AJAX原理
XMLHttpRequest(XHR)对象与服务器交互
<script>
//1.创建XMLHttpRequest对象
const xhr=new XMLHttpRequest()
//2.配置请求方法和请求url地址
xhr.open('请求方法','请求url网址')
//3.监听loadend事件,接收响应结果
xhr.addEventListener('loadend',()=>{
//响应结果
console.log(xhr.response)
})
//4.发起请求
xhr.send()
</script>
案例:读取省份
<p></p>
<script>
//1.创建XMLHttpRequest对象
const xhr=new XMLHttpRequest()
//2.配置请求方法和请求url地址
xhr.open('GET','http://hmajax.itheima.net/api/province')
//3.监听loadend事件,接收响应结果
xhr.addEventListener('loadend',()=>{
const data=JSON.parse(xhr.response).list.join('<br>')
document.querySelector('p').innerHTML=data
console.log(data)
})
//4.发起请求
xhr.send()
</script>
XHR查询参数
例:(查询省份)
<script>
/**
* 目标: 根据省份和城市名字, 查询对应的地区列表
*/
// 1. 查询按钮-点击事件
document.querySelector('.sel-btn').addEventListener('click', () => {
// 2. 收集省份和城市名字
const pname = document.querySelector('.province').value
const cname = document.querySelector('.city').value
// 3. 组织查询参数字符串
const qObj = {
pname,
cname
}
// 查询参数对象 -> 查询参数字符串
const paramsObj = new URLSearchParams(qObj)
const queryString = paramsObj.toString()
console.log(queryString)
// 4. 使用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)
document.querySelector('.list-group').innerHTML = htmlStr
})
xhr.send()
})
</script>
</body>
数据提交
例:(注册用户)
<button class="reg-btn">注册用户</button>
<script>
/**
* 目标:使用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'
}
const userStr = JSON.stringify(userObj)
// 设置请求体,发起请求
xhr.send(userStr)
})
</script>
Promise
Promise对象用于表示一个异步操作的最终完成(或失败)及其结果值
例:
<script>
/**
* 目标:使用Promise管理异步任务
*/
// 1. 创建Promise对象
const p = new Promise((resolve, reject) => {
// 2. 执行异步代码
setTimeout(() => {
// resolve('模拟AJAX请求-成功结果')
reject(new Error('模拟AJAX请求-失败结果'))
}, 2000)
})
// 3. 获取结果
p.then(result => {
console.log(result)
}).catch(error => {
console.log(error)
})
</script>
Promise三种状态
<script>
// 1. 创建Promise对象(pending-待定状态)
const p = new Promise((resolve, reject) => {
// Promise对象创建时,这里的代码都会执行了
// 2. 执行异步代码
setTimeout(() => {
// resolve() => 'fulfilled状态-已兑现' => then()
resolve('模拟AJAX请求-成功结果')
// reject() => 'rejected状态-已拒绝' => catch()
reject(new Error('模拟AJAX请求-失败结果'))
}, 2000)
})
console.log(p)
// 3. 获取结果
p.then(result => {
console.log(result)
}).catch(error => {
console.log(error)
})
</script>
案例:使用Promise+XHR获取省份列表
<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>
封装简易axios
<p class="my-p"></p>
<button class="reg-btn">注册用户</button>
<script>
/**
* 1. 定义myAxios函数,接收配置对象,返回Promise对象
* 2. 发起XHR请求,默认请求方法为GET
* 3. 调用成功/失败的处理程序
* 4. 使用myAxios函数,获取省份列表展示
*/
// 1. 定义myAxios函数,接收配置对象,返回Promise对象
function myAxios(config) {
return new Promise((resolve, reject) => {
// 2. 发起XHR请求,默认请求方法为GET
const xhr = new XMLHttpRequest()
if(config.params){
const paramsObj=new URLSearchParams(config.params)
const qString=paramsObj.toString()
config.url+=`?${qString}`
}
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
// 3. 调用成功/失败的处理程序
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()
}
})
}
document.querySelector('.reg-btn').addEventListener('click',()=>{
myAxios({
url:'http://hmajax.itheima.net/api/register',
method:'POST',
data:{
username:'cssssssssc',
password:'6666666'
}
}).then(result=>{
console.log(result)
}).catch(error=>{
console.log(error)
})
})
// 4. 使用myAxios函数,获取省份列表展示
myAxios({
url: 'http://hmajax.itheima.net/api/area',
params:{
pname:'辽宁省',
cname:'大连市'
}
}).then(result => {
console.log(result)
document.querySelector('.my-p').innerHTML = result.list.join('<br>')
}).catch(error => {
console.log(error)
document.querySelector('.my-p').innerHTML = error.message
})
</script>
同步代码和异步代码
-
同步代码:逐行执行,需原地等待结果后,才继续向下执行
-
异步代码:调用后耗时,不阻塞代码继续执行,在将来完成后触发一个回调函数,靠回调函数来接收成果
异步代码(例):setTimeout/setInterval,事件,AJAX
回调函数地狱
在回调函数中嵌套回调函数
<form>
<span>省份:</span>
<select>
<option class="province"></option>
</select>
<span>城市:</span>
<select>
<option class="city"></option>
</select>
<span>地区:</span>
<select>
<option class="area"></option>
</select>
</form>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/**
* 目标:演示回调函数地狱
* 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中
* 概念:在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱
* 缺点:可读性差,异常无法获取,耦合性严重,牵一发动全身
*/
// 1. 获取默认第一个省份的名字
axios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {
const pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
// 2. 获取默认第一个城市的名字
axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }}).then(result => {
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
// 3. 获取默认第一个地区的名字
axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }}).then(result => {
console.log(result)
const areaName = result.data.list[0]
document.querySelector('.area').innerHTML = areaName
})
})
}).catch(error => {
console.dir(error)
})
</script>
Promise链式调用
解决回调函数嵌套问题
<script>
/**
* 目标:掌握Promise的链式调用
* 需求:把省市的嵌套结构,改成链式调用的线性结构
*/
// 1. 创建Promise对象-模拟请求省份名字
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('北京市')
}, 2000)
})
// 2. 获取省份名字
const p2 = p.then(result => {
console.log(result)
// 3. 创建Promise对象-模拟请求城市名字
// return Promise对象最终状态和结果,影响到新的Promise对象
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result + '--- 北京')
}, 2000)
})
})
// 4. 获取城市名字
p2.then(result => {
console.log(result)
})
// then()原地的结果是一个新的Promise对象
console.log(p2 === p)
</script>
Promise解决回调函数地狱
案例:查找省,市,区
<form>
<span>省份:</span>
<select>
<option class="province"></option>
</select>
<span>城市:</span>
<select>
<option class="city"></option>
</select>
<span>地区:</span>
<select>
<option class="area"></option>
</select>
</form>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/**
* 目标:把回调函数嵌套代码,改成Promise链式调用结构
* 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中
*/
let pname = ''
// 1. 得到-获取省份Promise对象
axios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {
pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
// 2. 得到-获取城市Promise对象
return axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }})
}).then(result => {
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
// 3. 得到-获取地区Promise对象
return axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})
}).then(result => {
console.log(result)
const areaName = result.data.list[0]
document.querySelector('.area').innerHTML = areaName
})
</script>
async函数和await
<form>
<span>省份:</span>
<select>
<option class="province"></option>
</select>
<span>城市:</span>
<select>
<option class="city"></option>
</select>
<span>地区:</span>
<select>
<option class="area"></option>
</select>
</form>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/**
* 目标:掌握async和await语法,解决回调函数地狱
* 概念:在async函数内,使用await关键字,获取Promise对象"成功状态"结果值
* 注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)
*/
// 1. 定义async修饰函数
async function getData() {
// 2. await等待Promise对象成功的结果
const pObj = await axios({url: 'http://hmajax.itheima.net/api/province'})
const pname = pObj.data.list[0]
const cObj = await axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }})
const cname = cObj.data.list[0]
const aObj = await axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})
const areaName = aObj.data.list[0]
document.querySelector('.province').innerHTML = pname
document.querySelector('.city').innerHTML = cname
document.querySelector('.area').innerHTML = areaName
}
getData()
</script>
async,await捕获错误
try{
//要执行的代码
}catch(error){
//error接受的是错误信息
//try里的代码如果有错误,直接进入这里执行
}
<script>
/**
* 目标:async和await_错误捕获
*/
async function getData() {
// 1. try包裹可能产生错误的代码
try {
const pObj = await axios({ url: 'http://hmajax.itheima.net/api/province' })
const pname = pObj.data.list[0]
const cObj = await axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
const cname = cObj.data.list[0]
const aObj = await axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
const areaName = aObj.data.list[0]
document.querySelector('.province').innerHTML = pname
document.querySelector('.city').innerHTML = cname
document.querySelector('.area').innerHTML = areaName
} catch (error) {
// 2. 接着调用catch块,接收错误信息
// 如果try里某行代码报错后,try中剩余的代码不会执行了
console.dir(error)
}
}
getData()
</script>
事件循环
为什么有事件循环:JS是单线程的,为了不阻塞JS引擎,射击执行代码的模型
调用栈,宿主环境,任务队列
执行同步代码,遇到异步代码交给宿主浏览器环境执行,异步有了结果后,把回调函数放入任务队列排队,当调用栈空闲后,反复调用任务队列里的回调函数
宏任务与微任务
宏任务:由浏览器环境执行的异步代码
微任务:由JS引擎环境执行的异步代码(先调度)
Promise.all
都成功走then,有一个失败走catch
<ul class="my-ul"></ul>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/**
* 目标:掌握Promise的all方法作用,和使用场景
* 业务:当我需要同一时间显示多个请求的结果时,就要把多请求合并
* 例如:默认显示"北京", "上海", "广州", "深圳"的天气在首页查看
* code:
* 北京-110100
* 上海-310100
* 广州-440100
* 深圳-440300
*/
// 1. 请求城市天气,得到Promise对象
const bjPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '110100' } })
const shPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '310100' } })
const gzPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '440100' } })
const szPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '440300' } })
const p=Promise.all([bjPromise,shPromise,gzPromise,szPromise])
p.then(result=>{
const htmlStr=result.map(item=>{
return `<li>${item.data.data.area}--${item.data.data.weather}</li>`
}).join('')
document.querySelector('.my-ul').innerHTML=htmlStr
}).catch(error=>{
console.log(error)
})
</script>
标签:const,学习,xhr,AJAX,Promise,result,querySelector,document From: https://www.cnblogs.com/cyh822blogs/p/17571203.html