框架前置课-AJAX
AJAX
定义:它是异步的js和XML(Asynchronous JavaScript And XML),简单来说就是使用XMLHttpRequest对象与服务器通信。可以使用JSON,XML,HTML,text文本等格式发送和接受数据。它可以在不重新刷新页面的情况下与服务器通信,交换数据或更新页面。
- 如何使用AJAX
- 先使用axios库,与服务器进行数据通信
基于XMLHttpRequest封装,代码简单,
Vue,react项目都会用到axios - 再学习XMLHttpRequest对象,了解AJAX底层原理
axios使用
语法:
1.引入axios.js:https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js
2.使用axios函数
传入配置对象,再调用.then回调函数接收结果,并作后续处理
3. 需求:请求目标资源地址,拿到省份列表数据,显示到页面。
案例:
<!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>Document</title>
</head>
<body>
<p class="my-p">
</p>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><!--引入axios库-->
<script>
axios({/*引入后使用axios函数*/
url:'http://hmajax.itheima.net/api/province'/*输入目标资源地址*/
}).then(result=>{//对返回后的数据做后续处理
console.log(result)
console.log(result.data.list)//获取需要的数据
document.querySelector('.my-p').innerHTML=result.data.list.join('<br>')/*获取p标签,并把准备的省份列表插入页面*/
})
</script>
</body>
</html>
URL
统一资源定位符,简称网址,用于访问网络上的资源
http协议:规定浏览器和服务器之间传输数据的格式
格式:协议://域名/资源路径
- URL查询参数
定义:浏览器提供给服务器的额外信息。让服务器返回浏览器想要数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
axios-查询参数
语法:使用axios提供的params选项
axios在运行时会把参数名和值拼接到URL?参数名=值
<script>
axios({/*引入后使用axios函数*/
url:'http://hmajax.itheima.net/api/province',/*输入目标资源地址*/
params:{
pname:'辽宁省'
}
}).then(result=>{
console.log(result)
console.log(result.data.list)//获取需要的数据
document.querySelector('.my-p').innerHTML=result.data.list.join('<br>')/*获取p标签,并把准备的省份列表插入页面*/
})
</script>
地址查询
首先:确定URL网址和参数说明
- 查询某个省内某个城市的所有地区:http://hmajax.itheima.net/api/area
- 参数名:pname:省份名字或直辖市名字,比如北京,福建省…
cname:城市名字,比如北京市,厦门市…
<!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>Document</title>
<style>
.list-group{
list-style:none;
display:block;
width:200px;
height:30px;
border:1px solid;
line-height:30px;
text-align:center;
}
</style>
</head>
<body>
<div class="container">
<form id="editForm" class="row">
<!--输入省份名字-->
<div class="mb-3 col">
<lable class="form-lable">省份名字</lable>
<input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名字">
</div>
<div class="mb-3 col">
<lable class="form-lable">城市名字</lable>
<input type="text" value="北京市" name="city" class="from-control city" placeholder="请输入城市名字">
</div>
</form>
<button type="button" class="btn btn-primary sel-btn">查询</button>
<br>
<p>地区列表:</p>
<ul class="list-group">
<li class="list-group-items">
东城区
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><!--引入AJAX地址-->
<script>
document.querySelector('.sel-btn').addEventListener(
'click',()=>{
//获取省份和城市
let pName=document.querySelector('.province').value
let cName=document.querySelector('.city').value
//基于axios请求地区列表数据
axios({
url:'http://hmajax.itheima.net/api/area',
params:{
pname:pName,
cname:cName
}
}).then(result=>{
let list=result.data.list
console.log(list)
let theli= list.map(areaName =>`<li class="list-group-items">${areaName}</li>`).join('')
console.log(theli)
document.querySelector('.list-group').innerHTML=theli
})
}
)
</script>
</body>
</html>
- 常用请求方法和数据提交
请求方法:对服务器资源数据执行操作
请求方法 操作
GET 获取数据
POST 提交数据
PUT 修改数据(全部)
BELETE 删除数据
PATCH 修改数据(部分)
数据提交:当数据需要在服务器上面保存
axios请求配置:
url:请求的URL网址
method:请求的方法,GET可省略(不区分大小写)
params:查询参数
data:提交数据
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><!--引入AJAX地址-->
<script>
document.querySelector('.btn').addEventListener(
'click',()=>{
axios({
url:'http://hmajax.itheima.net/api/register',
//指定请求方法
method:'post',//'get'params:{
}
data:{
username:'itheima113',
password:'123456'
}
}).then(result=>{
console.log(result)
})
}
)
</script>
- axios错误处理
再次注册相同的账号时,会出现报错的情况,处理方法是用直观方法给普通用户展示错误信息
语法:在then方法的后面,通过语法调用catch方法,传入回调函数并定义形参
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><!--引入AJAX地址-->
<script>
document.querySelector('.btn').addEventListener(
'click',()=>{
axios({
url:'http://hmajax.itheima.net/api/register',
//指定请求方法
method:'post',
data:{
username:'itheima113',
password:'123456'
}
}).then(result=>{
console.log(result)
}).catch(error=>{
console.log(error)
console.log(error.response.data.message)
alert(error.response.data.message)
})
}
)
</script>
HTTP协议请求报文
http协议:规定了浏览器发送及服务器返回内容的格式
请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容
请求报文组成格式:
- 请求行:请求方法,URL,协议
- 请求头:以键值对的格式携带的附加信息,比如:Content-Type(本次浏览器携带的内容类型)
- 空行:分隔请求头,空行之后的是发送给服务器的资源
- 请求报文错误排查:
响应报文:
- 响应行(状态行):协议,http响应状态码,状态信息
- 响应头:以键值对的格式携带的附加信息,比如:content-Type
- 空行:分隔响应头,空行之后是服务器返回的资源,
- 响应体:返回的资源
响应状态码:用来表明请求是否成功完成。
状态码 说明
1XX 信息
2xx 成功
3XX 重定向消息
4XX 客户端错误
5XX 服务器端错误
404:服务器找不到资源
- 接口文档
接口文档:描述接口的文章(后端工程师提供)
接口:使用AJAX和服务器通讯时,使用的URL,请求方法,以及参数
<!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>Document</title>
<style>
.form-control{
display:block;
width:150px;
height:30px;
border-radius:4px;
border:1px solid gray;
}
.form-lable{
display:block;
color:gray;
margin-bottom:10px;
}
.btn{
margin-top:30px;
background:blue;
}
.mb-3{
margin-top:10px;
}
.container{
width:250px;
height:250px;
margin:0 auto;
}
.alert-success{
width:150px;
height:30px;
opacity:0
}
.show{
opacity:1;
}
.alert-sccess{
background-color:aqua
}
.alert-danger{
background-color: red;
}
</style>
</head>
<body>
<div class="container">
<h3>
欢迎-登录
</h3>
<div class="alert alert-success" role="alert">
提示消息
</div>
<div class="form_wrap">
<form>
<div class="mb-3">
<lable for="username" class="form-lable">账号名</lable>
<input type="text" class="form-control username">
</div>
<div class="mb-3">
<lable for="password" class="form-lable">密码</lable>
<input type="password" class="form-control password">
</div>
<button type="button" class="btn btn-primary btn-login">登录</button>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><!--引入AJAX地址-->
<script>
//获取提示框
const myAlert=document.querySelector('.alert')
//实现封装反复调用满足提示要求
/**1.显示提示框,2,不同提示文字msg,和成功绿色失败红色isSuccess(true成功,false失败)
* 过两秒后提示框自动消失*/
function alertFu(msg,isSuccess){
//显示提示框
myAlert.classList.add('show')
myAlert.innerHTML=msg
const bgStyle=isSuccess?'alert-sccess':'alert-danger'
myAlert.classList.add(bgStyle)
//过两秒后隐藏
setTimeout(()=>{
myAlert.classList.remove('show')
myAlert.classList.remove(bgStyle)
},2000)
}
//绑定点击事件
document.querySelector('.btn-login').addEventListener(
'click',()=>{
//获取用户名和密码
const username=document.querySelector('.username').value
const password=document.querySelector('.password').value
console.log(username,password)
//判断长度
if(username.length<8){
alertFu('用户名必须大于八位',false)
return;
}
if(password.length<6){
alertFu('用户密码必须大于6位',false)
return;
}
//基于axios提交用户名和密码
axios({
url:"http://hmajax.itheima.net/api/login",
method:'post',
data:{
username:username,
password:password
}
}).then(result=>{
console.log(result)
alertFu('登录成功',true)
}).catch(error=>{
console.log(error)
alertFu('登录失败',false)
})
}
)
</script>
</body>
</html>
form-serialize插件
作用是快速收集表单元素的值
利用插件中的serialize函数快速收集表单元素的值
参数1:要获取数据的表单
表单元素设置name属性,值会作为对象的属性名
建议name属性值与接口文档参数名一致
参数2:配置对象
- hash 设置获取数据结构
ture:js对象(推举)一般请求体里提交给服务器
false:查询字符串 - empty 设置是否获取空值
ture:获取空值,数据结构和标签结构一致
false:不获取空值
<body>
<form class="ex-f">
<input type="text" name="username">
<input type="password" name="password">
<button type="button" class="btn">提交</button>
</form>
<script src="./form-serialize.js"></script>
<script>
document.querySelector('.btn').addEventListener('click',()=>{
const form=document.querySelector('.ex-f')
const data=serialize(form,{hash:true,empty:true})
console.log(data)
})
</script>
Bootstrap
下载后解压,将需要的js和css文件复制的项目同一目录下,然后在代码中引入。
bootstrap栅格系统:实现响应式布局效果,栅格化是指将整个网页的宽度分成12等份,每个盒子占用的对应份数。如:一行排4个盒子,则每个盒子占3份
bootstrap5划分了视口范围,称为响应断点,做响应式效果要保证版心不同。
Contalner调用这个类名可以实现响应式布局的版心效果,例如如果要在xl这个屏幕范围一行排四个,类名调用就用col-xl-4(先添加row类名)(屏幕范围xs:<576px|sm:>=576px|md:>=768px|lg:>=992px|xl:>=1200px|xxl:>=1400px),这种写法为在类前缀后面加上对应份数。
<!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>Document</title>
<link href="./bootstrap/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!--视口宽大于等于1200px,一行排4个盒子(每个盒子再3分)-->
<!--视口宽度大于等于768px,一行排2个(每个盒子占6份)-->
<!--视口宽度大于等于576px,一行排1个(每个盒子占6份)-->
<!--版心——row——子集-->
<div class="container">
<div class="row">
<div class="col-xl-3 col-md-6 col-sm-12">1</div>
<div class="col-xl-3 col-md-6 col-sm-12">2</div>
<div class="col-xl-3 col-md-6 col-sm-12">3</div>
<div class="col-xl-3 col-md-6 col-sm-12">4</div>
</div>
</div>
</body>
</html>
- bootstrap全局样式
给网页元素调用类名用来美化网页元素。
Button类
btn:默认样式(会清楚按钮背景色边框等等)
btn-success:成功(蓝色按钮)
btn-warning:警告(橙色按钮)
btn-lg/btn-sm:按钮尺寸
<button class="btn">1</button>
<button class=" btn btn-success">2</button>
需要的样式可以看文档去复制
表格类:
table:默认样式
table-striped:隔行变色
table-success:表格颜色
…
<table class="table table-striped">
<tr >
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<table class="table table-striped">
<tr class="table-success">
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
- Bootstrap-组件(Components)
- 引入样式表
- 引入js(如果组件有动态功能则需要引入js)
- 复制结构,修改内容
- Bootstrap-字体图标
下载:导航/Extend:图标库->安装->下载安装包->bootstrap-icons-1.X.X.zip
使用:
- 复制fonts文件夹到项目目录
- 网页引入bootstrap-icons.css文件
- 调用css类名(图标对应的类名)
- bootstrap弹框
不离开当前页面,显示单独内容,供用户操作
步骤:
- 引入bootstrap.css和bootstrap.js
- 准备弹框标签,确认结构
- 通过自定义属性(data-bs-toggle=“model"和data-bs-target=''css选择器”//前者添加后点击按钮后会出现model弹框,后面加css选择器是为了限制哪一个model),控制弹框的显示和隐藏
- 使用bootstrap的modal弹框,先要添加类名
通过js代码来控制显示和隐藏:
<script>
const modalDom=document.querySelector('.my-box')
const modal=new bootstrap.Modal(modalDom)//通过Modal方法得到一个和类名对应的弹框
//点击编辑按钮显示弹框
document.querySelector(".edit-na").addEventListener(
'click',()=>{
//赋予默认姓名
document.querySelector('.username').value='默认姓名'
//用弹框对象调用show方法
modal.show()
}
)
//保存点击事件先隐藏
document.querySelector('.save-btn').addEventListener(
'click',()=>{
const a=document.querySelector('.username').value//获取姓名
console.log(a)
modal.hide()
}
)
</script>
图书管理-渲染列表:
自己的图书数据:给自己取一个外号,并告诉服务器,默认会有3本书,基于这个数据做增删改查
1.获取图书列表
2.渲染数据
在点击编辑时,将需要编辑的数据获取到,需要传图书id
addEventListener方法:可设置多个事件,并且可以自主的定义事件触发顺序是冒泡还是捕获,还可设置移动端的触发事件,如touchstart等等,
冒泡:事件发生顺序是一层层向上传递的,直到HTML根事件,addEventListener的函数第三个参数是true时
捕获事件:从HTML一层一层向下传递,直到具体位置点,addEventListener函数第三个参数是false时。
key-forEach
JavaScript中的Object.keys()方法用于返回给定对象的自身可枚举属性名称的数组。它接受一个对象作为参数,并返回一个包含该对象自身属性名称的数组。
例如:
const person = {
name: ‘John’,
age: 30,
city: ‘New York’
};
const keys = Object.keys(person);
console.log(keys); // 输出: [‘name’, ‘age’, ‘city’]
在这个例子中,Object.keys()方法用于获取person对象的键的数组。输出将是一个包含属性名称’name’、'age’和’city’的数组。
图片上传
- 获取图片文件(以前传的都是数字和字符串,可以转成json字符串,文件不能转成json字符串,只能用form-data类型来携带文件)
- 使用浏览器内置FormData构造函数携带图片文件
const fd=new FormData()
fd.append(参数名,值)
- 提交表单数据到服务器,使用图片URL网址
<!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>Document</title>
</head>
<body>
<input type="file" class="upload">
<img src="" class="my-poto">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script >
document.querySelector('.upload').addEventListener('change',e=>{
console.log(e.target.files[0])//使用.files属性返回一个文件元素列表,后面加0拿到文件对象
//用FormData携带文件
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)
const imgl=result.data.data.url
document.querySelector('.my-poto').src=imgl
})
})
</script>
</body>
</html>
- lable标签
label 标签在 HTML 中的主要作用是为表单控件提供标签文本,并且可以改善用户体验。以下是 label 标签的一些主要用途:
- 关联表单元素:label 标签通过 for 属性和表单控件的 id 属性进行关联,从而使用户点击标签文本时能够激活相关的表单控件。这样可以扩大用户点击的范围,提高交互的友好性。
<label for="username">Username:</label>
<input type="text" id="username">
-
提供可点击的标签:用户可以点击 label 标签来聚焦或选择相关的表单控件,而不仅仅是点击表单控件本身。
-
增强可访问性:使用 label 标签可以增强网页的可访问性。屏幕阅读器等辅助技术可以识别 label 标签,帮助用户更好地理解表单控件的用途。
样式设计:label 标签可以用于设计和布局,使表单更具有美感和可读性。
- localStorage
- localStorage 和 sessionStorage 属性允许在 Web 浏览器中保存键/值对。
localStorage 对象存储没有到期日期的数据。浏览器关闭时数据不会被删除,并且会在第二天、周或一年后可用。 - 例子:创建一个 name=“lastname” 和 value=“Smith” 的 localStorage 名称/值对,然后检索 “lastname” 的值并将其插入到 id=“result” 的元素中:
// 存储
localStorage.setItem("lastname", "Smith");
// 取回
document.getElementById("result").innerHTML = localStorage.getItem("lastname");
<!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>Document</title>
</head>
<body>
<label for="fd">选择</label>
<input type="file" class="upload" id="fd">
<img src="" class="my-poto">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script>
document.querySelector('.upload').addEventListener('change', e => {
const nef = new FormData();
nef.append('img', e.target.files[0]);
axios({
url: "http://hmajax.itheima.net/api/uploadimg",
method: 'POST',
data: nef
}).then(result => {
const img = result.data.data.url
document.body.style.backgroundImage = `url(${img})`
localStorage.setItem('bg', img)
});
});
const bgl=localStorage.getItem('bg')
bgl&&(document.body.style.backgroundImage = `url(${bgl})`)
</script>
</body>
</html>
- 案例个人信息设置
- 打开页面前先将用户信息渲染在页面
axios({
url:'http://hmajax.itheima.net/api/settings',
params:{creator:'比较'}
}).then(result=>{
const usna=result.data.data
//获取后回显在页面
Object.keys(usna).forEach(key=>{
//性别和头像单独设置
if(key==='avatar'){
document.querySelector('.prew').src=usna[key]
}else if(key==='gender'){
const n= document.querySelectorAll('.gender')
const mn=usna[key]
n[mn].checked=true
}else{
document.querySelector(`.${key}`).value=usna[key]
}
})
})
- 设置头像
document.querySelector('.upload').addEventListener('change',e=>{
const bg=new FormData()
bg.append('avatar',e.target.files[0])
bg.append('creator',creator)//确定是谁要修改头像
axios({
url:'http://hmajax.itheima.net/api/avatar',
method:'PUT',
data:bg
}).then(result=>{
const ig=result.data.data.avatar
document.querySelector('.prew').src=ig
})
})
- 个人信息修改
document.querySelector('.submit').addEventListener('click',()=>{
const userFrom=document.querySelector('.user-form')
const us=serialize(userFrom,{hash:true,empty:true})//通过form-serialize插件收集信息
us.creator=creator//创建creator属性
us.gender=+us.gender//将字符串数字转化为数字类型
axios({
url:'http://hmajax.itheima.net/api/settings',
method:'put',
data:us
})
})
- 结果提示框
- Modal和Toast区别
- Modal是一个弹出式窗口,通常用于展示重要的信息、进行用户交互或显示一个表单。
- Modal会阻止用户与页面的其他部分进行交互,用户需要在模态框关闭之前完成相应的操作。
- Modal通常包含一个标题、内容区域和操作按钮,可以显示更多详细信息和提供更多操作选项。
Toast(消息提示框): - Toast是一种轻量级的消息提示框,通常用于展示一些简短的提示信息或反馈。
- Toast通常会自动消失或在一段时间后自动关闭(通过data-bs-delay设置值),不会阻止用户与页面的其他部分进行交互。
- Toast通常只包含一段文本信息,用于向用户展示一些提示、警告或成功信息。
axios({
url:'http://hmajax.itheima.net/api/settings',
method:'put',
data:us
}).then(result=>{
const toam=document.querySelector('.my-toast')
const tost=new bootstrap.Toast(toam)
tost.show()
})
})
AJAX原理-XMLHttpRequest
XMLHttpRequest(XHR)对象用于与服务器交互,通过他可以在不刷新页面的情况下请求特定URL,这允许网页在不影响用户操作的情况下更新页面局部内容。
axios与XMLHttpRequest的关系:axios内部采用XMLHttpRequest与服务器交互。
- 使用XMLHttpRequest
- 创建对象
- 配置请求方法和请求URL地址
- 监听loadend事件,接收响应效果
- 发起请求
<script>
const xhr=new XMLHttpRequest()//创建对象
xhr.open('GET','http://hmajax.itheima.net/api/province')//配置请求方法和请求网址
xhr.addEventListener('loadend',()=>{
console.log(xhr.response)//调用xhr对象里面固定的属性,查看响应结果
//获取的数据是json字符串,axios会将返回数据转化成js对象,而原生XHR对象不会自动转换。
const su= JSON.parse(xhr.response)//将json字符串转化为对象
console.log(su)
console.log(su.list.join('<br>'))
document.querySelector(".my").innerHTML=su.list.join('<br>')
})//绑定loadend事件,接收响应结果,该事件无论成功和失败都会执行回调函数
xhr.send()//发起请求
</script>
- XMLHttpRequest查询参数
定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据。
语法:http://xxxx.com/xxx/xxx?参数名1=参数值&参数名2=值2
<script>
const xhr=new XMLHttpRequest()//创建对象
xhr.open('GET','http://hmajax.itheima.net/api/city?pname=辽宁省')//配置请求方法和请求网址
xhr.addEventListener('loadend',()=>{
const data=JSON.parse(xhr.response)
const ne=document.querySelector('.my').innerHTML=data.list.join('<br>')
console.log(ne)
})
xhr.send()
</script>
- URLSearchParams对象
可以通过他将一个js对象转换为查询参数字符串的样式 - map和forEach方法区别
- forEach: forEach 方法不会返回一个新的数组,它只是遍历数组中的每个元素并执行指定的回调函数,但不会改变原始数组。
- map: map 方法会返回一个新的数组,该数组包含对原始数组中每个元素应用回调函数的结果。
副作用: - forEach: forEach 方法会对数组中的每个元素执行回调函数,但不会返回任何值。它通常用于执行副作用,如修改数组中的元素或执行一些操作。
- map: map 方法会对数组中的每个元素应用回调函数,并返回一个新的数组,而不会修改原始数组。它通常用于将数组中的每个元素映射到新的值。
<!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>Document</title>
</head>
<body>
<button class="btn">查询</button>
<input type="text" class="pname" placeholder="请输入" value="北京">
<input type="text" class="cname" placeholder="请输入" value="北京市">
<p class="my"></p>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script>
document.querySelector('.btn').addEventListener('click',()=>{
const pname=document.querySelector('.pname').value
const cname=document.querySelector('.cname').value
const qobj={
pname,
cname
}
const qaramsobj=new URLSearchParams(qobj)//创建URLSearchParams对象
const par=qaramsobj.toString()
const xhr=new XMLHttpRequest()
xhr.open('GET',`http://hmajax.itheima.net/api/area?${par}`)
xhr.addEventListener('loadend',()=>{
console.log(xhr.response)
})
xhr.send()
})
</script>
</body>
</html>
- XMLHttpRequest-数据提交
需求:通过XHR提交用户名和密码完成注册功能
请求头设置Content-Type:application/json
请求体携带json字符串
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script>
document.querySelector('.btn').addEventListener('click',()=>{
const xhr=new XMLHttpRequest()
xhr.open('POST','http://hmajax.itheima.net/api/register')
xhr.addEventListener('loadend',()=>{
console.log(xhr.response)
})
xhr.setRequestHeader('Content-Type','application/json')//设置请求头,告诉服务器内容类型(由接口文档提供此处为json字符串)
//准备提交的数据
const obj={
username:'ithem12344',
password:'12345345'
}
const userobj=JSON.stringify(obj)//将对象转为json字符串
//设置请求体,发起请求
xhr.send(userobj)
})
</script>
Promise
定义:用于表示一个异步操作的最终完成(或失败)及其结果值
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script>
//使用Promise管理异步任务
//创建Promise对象
const p=new Promise((resolve,reject)=>{//形参是Promise提供的两个函数
//执行异步代码-并传递结果
setTimeout(()=>{
resolve('模拟请求成功结果')//成功后执行then()后面的操作
reject(new Error('模拟请求失败'))//失败后执行catch()后面的操作
},2000)
})
//获取结果
p.then(re=>{
console.log(re)
}).catch(er=>{
console.log(er)
})
</script>
- Promise三种状态
作用:了解Promise对象如何关联的处理函数,以及代码执行顺序
一个Promise对象必定处于以下三种状态之一:
待定(pending):初始状态,既没有被兑现也没有被拒绝
已兑现(fulfilled):意为着操作成功完成
已拒绝(rejected):意为着操作失败
注:promise对象一旦被兑现/拒绝就是已经敲定,状态无法改变
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script>
//使用Promise管理异步任务
//创建Promise对象
const p=new Promise((resolve,reject)=>{//形参是Promise提供的两个函数
console.log('测试')//Promise对象创建后就会执行下面的代码
//执行异步代码
setTimeout(()=>{
resolve('模拟请求成功结果')//成功后执行.then后面的操作
reject(new Error('模拟请求失败'))//失败后执行.catch后面的操作
},2000)
})
console.log(p)//状态先变成fulfilled后就无法被改变了
//获取结果
p.then(re=>{
console.log(re)
}).catch(er=>{
console.log(er)
})
</script>
- 案例:使用Promise+XML获取省份列表
需求:实用Promise管理XML获取省份列表,并展示在页面上
步骤:
- 创建Promise对象
- 执行XML异步代码,获取省份列表
- 关联成功或失败函数,做后续处理
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script>
//使用Promise管理异步任务
//创建Promise对象
const p=new Promise((resolve,reject)=>{
const obj=new XMLHttpRequest()
obj.open('GET','http://hmajax.itheima.net/api/province')
obj.addEventListener('loadend',()=>{
if (obj.status>=200&&obj.status<300){
resolve(JSON.parse(obj.response))
}else{
reject(new Error(obj.response))
}
})
obj.send()
})
p.then(re=>{
document.querySelector('.my').innerHTML=re.list.join('<br>')
}).catch(er=>{
document.querySelector('.my').innerHTML=er
})
</script>
- 封装_简易axios_获取省份列表
需求:基于Promise+XMR封装myAxios函数,获取省份列表展示
步骤:
- 定义myAxios函数,接收配置对象,返回Promise对象
- 发起XMR请求,默认请求方法为GET
- 调用成功/失败处理程序
- 使用myAxios函数,获取省份列表
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script>
function myAxios(congin){//定义形参,根据形参获取传进来的method/URL等等
return new Promise((resolve,reject)=>{
const obj=new XMLHttpRequest()
obj.open(congin.method||'GET',congin.url)
obj.addEventListener('loadend',()=>{
if (obj.status>=200&&obj.status<300){
resolve(JSON.parse(obj.response))
}else{
reject(new Error(obj.response))
}
})
obj.send()
})
}
myAxios({
url:'http://hmajax.itheima.net/api/province'
}).then(re=>{
document.querySelector('.my').innerHTML=re.list.join('<br>')
}).catch(er=>{
document.querySelector('.my').innerHTML=er
})//通过返回的Promise对象调用他的两个方法
- 封装_简易axios_获取地区列表
需求:修改myAxios函数支持传递查询参数,会获取辽宁省,大连市对应地区列表显示
需求:myAxios函数调用后,传入params选项
要求:
- myAxios函数调用后,传入params选项
- 基于URLSearchParams转换查询参数
- 使用封装的函数查询
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script>
function myAxios(congin){//定义形参,根据形参获取传进来的method/URL等等
return new Promise((resolve,reject)=>{
const obj=new XMLHttpRequest()
if(congin.params){
const paramsobj=new URLSearchParams(congin.params)
const poj= paramsobj.toString()
congin.url+=`?${poj}`//把查询参数字符串拼接到后面
}
obj.open(congin.method||'GET',congin.url)
obj.addEventListener('loadend',()=>{
if (obj.status>=200&&obj.status<300){
resolve(JSON.parse(obj.response))
}else{
reject(new Error(obj.response))
}
})
obj.send()
})
}
myAxios({
url:'http://hmajax.itheima.net/api/area',
params:{
pname:'辽宁省',
cname:'大连市'
}
}).then(re=>{
document.querySelector('.my').innerHTML=re.list.join('<br>')
}).catch(er=>{
document.querySelector('.my').innerHTML=er
})
</script>
- 封装_简易axios_注册用户
需求:修改myAxios函数支持传递请求体数据,完成注册用户功能·
步骤:
- myAxios函数调用后,判断data选项
- 转换数据类型,在send方法中发送
- 使用自己封装的myAxios完成注册
<script>
function myAxios(congin){//定义形参,根据形参获取传进来的method/URL等等
return new Promise((resolve,reject)=>{
const obj=new XMLHttpRequest()
if(congin.params){
const paramsobj=new URLSearchParams(congin.params)
const poj= paramsobj.toString()
congin.url+=`?${poj}`//把查询参数字符串拼接到后面
}
obj.open(congin.method||'GET',congin.url)
obj.addEventListener('loadend',()=>{
if (obj.status>=200&&obj.status<300){
resolve(JSON.parse(obj.response))
}else{
reject(new Error(obj.response))
}
})
if(congin.data){
const c=JSON.stringify(congin.data)
obj.setRequestHeader('Content-Type','application/json')
obj.send(c)
}else{
obj.send
}
})
}
myAxios({
url:'http://hmajax.itheima.net/api/register',
method:'POST',
data:{
username:'sdfsdfsfvvdf',
password:'12345667'
}
}).then(re=>{
// document.querySelector('.my').innerHTML=re.list.join('<br>')
console.log(re)
}).catch(er=>{
console.dir(er)
})
</script>
- 案例-天气查询
同步代码和异步代码
同步代码:实际上浏览器是按我们书写代码的顺序一步一步执行程序的,浏览器会等待代码的解析和工作,在上一行完成后才会执行下一行,这样是很有必要的,因为每一行新代码都建立在前面代码的基础上。这也使得他成为一个程序
异步代码:异步编程技术使程序可以在执行一个可能长期运行的任务的同时继续对其他的事件作出反应而不必等待任务完成,与此同时,程序也将在任务完成后显示结果
- js有哪些异步代码
setTimeout/setInterval
事件
AJAX
异步代码如何接收结果:依靠回调函数来接收 - 回调函数地狱
概念:在一个回调函数中嵌套回调函数,一直嵌套下去就形成了回调地狱
缺点:可读性差,异常无法捕获,耦合严重,牵一发动全身 - Promise-链式调用
概念:依靠then()方法会返回一个新生成的Promise对象特性,继续串联下一环任务直到结束
<script>
const params=new Promise((resolve,reject)=>{//模拟请求省份名字
setTimeout(()=>{
resolve('北京市')
},2000)
})
//获取省份名字
const p2=params.then(result=>{
console.log(result)
//创建Promise对像模拟请求城市名字
//return Promise对象最终状态和结果,影响到新的Promise对象
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(result+'---北京')
},2000)
})
})
//获取城市名字
p2.then(result=>{
console.log(result)
})
</script>
- async函数和await
定义:async函数是使用async关键字声明的函数,async函数是AsyncFunction构造函数的实例,并且其中允许使用await关键字,async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无须刻意链式调用promise
概念:在asyce函数内使用await关键字取代then函数,等待获取Promise对象成功获取状态的结果值
<script>
async function getData(){
const pobj=await axios({url:'http://hmajax.itheima.net/api/province'})
const pname=pobj.data.list[0]
const cobj=await axios({url:'',params:{pname}})
document.querySelector('.province').innerHTML=pname
}
getData()
- async函数和await_捕获错误
使用:try…catch 在try后面包含可能出错的语句,在catch后面
<script>
async function getData(){
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/city1',params:{pname}})
document.querySelector('.province').innerHTML=pname
}catch(er){
console.dir(er)
}
}
getData()
</script>
- 事件循环
好处:掌握js如何安排和运行代码的
概念:js有一个基于事件循环的并发模型,事件循环负责执行代码,收集和处理事件以及执行队列中的子任务,这个模型与其他语言中的模型截然不同
为什么要设计事件循环模型的原因:js单线程(某一时刻只能执行一行代码),为了让耗时代码不阻塞其他代码运行,设计了事件循环模型
定义:执行代码和收集异步任务的模型,在调用栈空闲时,反复调用任务队列里回调函数的执行机制,就叫事件循环
js内代码如何执行:
执行同步代码,遇到异步代码交给宿主浏览器环境执行
异步有了结果后,把回调函数放入任务队列排队,当调用栈空闲后,反复调用任务栈里面的回调函数 - 宏任务和微任务
ES6之后引入了Promise对象,让js引擎也可以发起异步任务
异步任务可分为:
- 宏任务:由浏览器环境执行的异步代码
js脚本执行事件(script),setTimeout/setInterval,AJAX请求完成事件,用户交互事件等 - 微任务:由js引擎环境执行的异步代码
Promise对象.then()(Promise本身是同步的,而then,catch回调函数是异步的)
调用栈会先调用微任务里面的回调函数,直到微任务清空后才会执行下一个宏任务
- Promise.all静态方法
概念:合并多个Promise对象,等待所有都成功完成(或某一个失败),做后续逻辑处理