以下笔记均为学习哔站黑马程序员AJAX视频所得!!!
AJAX作用:浏览器和服务器之间通信,动态数据交互
axios函数
先引入axios库,可在bootcdn中寻找相关js文件或者对应的script标签
axios({
url:'http://hmajax.itheima.net/api/provice'//获取数据的地址
}).then(result=>{
console.log(result)//一个对象
console.log(result.data.list)//一个数组
console.log(result.data.list.join('<br>'))//将数组中的元素以换行线隔开
document.querySelector('p').innerHTML=result.data.list.join('<br>')
})
URL
- http协议:超文本传输协议,规定浏览器和服务器之间传输数据的格式
- 域名:标记服务器在互联网中方位(必须)
- 资源路径:标记资源在服务器下的具体位置
axios({ url:'http://hmajax.itheima.net/api/city', // 查询参数 params:{ pname:'辽宁省'//最终只会提取出辽宁省下面的部分,其他省的城市不会出现 } }).then(result=>{ console.log(result.data.list) document.querySelector('p').innerHTML=result.data.list.join('<br>') })
URL查询参数
定义:浏览器提供给服务的额外信息,让服务器返回浏览器想要的数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
作用:浏览器提供给服务器额外的信息,获取对应的数据
axios-查询参数
语法:使用axios提供的params选项
注意:axios在运行时把参数名和值,会拼接到url?参数名=值
地区查询(从服务器中获取数据)
需求:根据输入的省份名字和城市名字,查询地区并渲染列表
首先:确定URL网址和参数说明
- 查询某个省内某个城市的所有地区:http://hmajax.itheima.net/api/area
- 参数名:
- pname:省份名字或直辖市名字,比如北京,福建省,辽宁省
- cname:城市名字,比如北京市,厦门市,大连市
完整:http://hmajax.itheima.net/api/area?pname=北京&cname=北京市
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
:root {
font-size: 15px;
}
body {
padding-top: 15px;
}
.mb-3 {
display: inline-block;
}
li {
list-style: none;
}
</style>
</head>
<body>
<div class="container">
<form id="ediForm" class="row">
<div class="mb-3 col">
<label class="form-lable">省份名字</label>
<input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名称" >
</div>
<div class="mb-3 col">
<label class="form-lable">城市名字</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>
<p>地区列表:</p>
<ul class="list-group">
<!-- 实例地区 -->
<li class="list-group-item">东城区</li>
</ul>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.6.8/axios.min.js"></script>
<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//pname和cname为后端规定接口,不可随意改变,当要传进去的参数和pname,cname同名时,可以简化,params中只写pname,cname
}
}).then(result=>{
// 把数据转成li标签 插入到页面上
let list=result.data.list
console.log(list)
let theLi=list.map(areaName=>`
<li class="list-group-item">${areaName}</li>
`).join('')
document.querySelector('.list-group').innerHTML=theLi
})//theLi里面包含了很多个li标签,将其转化为字符串用join
})
</script>
</body>
</html>
常用请求方法:
请求方法:对服务器资源,要执行的操作
请求方法 | 操作 |
---|---|
GET | 获取数据 |
POST | 提交数据 |
PUT | 修改数据 |
DELETE | 删除数据 |
PATCH | 修改数据(部分) |
数据提交
当数据需要在服务器上保存
axios请求配置
- url:请求的URL地址
- method:请求的方法,GET方法可以省略(不区分大小写)
- data:提交数据
数据提交-注册账号
- 需求:通过axios提交用户名和密码,完成注册功能
- 注册用户URL地址:http://hmajax.itheima.net/api/register
- 请求方法:POST
参数名:
username 用户名(中英文和数字组成,最少8位)
password密码(最少6位)
// 目标:点击按钮,通过axios提交用户和密码,完成注册
document.querySelector('.btn').addEventListener('click',()=>{
axios({
url:'http://hmajax.itheima.net/api/register',
// 指定请求方法
method:'post',
// 提交数据
data:{
username:'zj05090429',
password:'123456'
}
}).then(result=>{
console.log(result)
})
})
在上述代码中,再次注册相同的账号,会遇到报错信息,提示,账号已被占用
axios错误处理
场景:再次注册相同的账号,会遇到报错处理
处理:用更直观的方式,给普通用户展示错误信息,如下:
语法:在then方法的后面,通过点语法调用catch方法,传入回调函数并定义形参
处理:注册案例,重复注册时通过弹框提示用户错误原因
axios({
url:'http://hmajax.itheima.net/api/register',
// 指定请求方法
method:'post',
// 提交数据
data:{
username:'zj05090429',
password:'123456'
}
}).then(result=>{
// 成功
console.log(result)
}).catch(error=>{
// 失败
// 处理错误信息
// console.log(error)
// console.log(error.response.data.message)
alert(error.response.data.message)
})
})
HTTP协议-请求报文
HTTP协议:规定了浏览器发送及服务器返回内容的格式
请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容
请求报文的组成部分有:
1.请求行:请求方法,URL,协议
2.请求头:以键值对的格式携带的附加信息,比如:Content-type
3.空行:分隔请求头,空行之后的是发送给服务器的资源
4.请求体:发送的资源
最终会将传入的数据对象转化为JSON字符串携带到请求报文中
请求报文-错误排查,可通过查看载荷中传入的数据进行分析排查
HTTP协议-响应报文
响应报文:服务器按照HTTP协议要求的格式,返回给浏览器的内容
1.相应行(状态行):协议、HTTP响应状态码、状态信息
2.相应头:以键值对的格式写到的附加信息,比如:Content-Type
3.空行:分隔响应头,空行之后的是服务器返回的资源
4.响应体:返回的资源
HTTP响应状态码:用来表明请求是否成功完成
比如:404(服务器找不到资源)
状态码 | 说明 |
---|---|
1xx | 信息 |
2xx | 成功 |
3xx | 重定向消息 |
4xx | 客户端错误 |
5xx | 服务端错误 |
接口文档
接口文档:描述接口的文章
接口:使用AJAX和服务器通讯时,请求方法,以及参数
axios({
url:'http://hmajax.itheima.net/api/login',
method:'post',
data:{
username:'itheima007',
password:'7654321'
}
})
})
案例-用户登录
1.点击登录时,判断用户名和密码长度
2.提交数据和服务器通信
3.提示信息
const myAlert=document.querySelector('.alert')
// 封装提示框函数,重复调用 满足提示需求
// 功能:
// 1.显示提示显示框
// 2.不同提示文字msg,和成功绿色失败红色 issucess(true成功,false失败)
// 3.过两秒之后,让提示框自动消失
function alertFn(msg,isSucess){
// 显示提示框
myAlert.classList.add('show')
// 实现细节
myAlert.innerText=msg
const bgStyle=isSucess?'alert-sucess':'alert-danger'//boootstrap框架
myAlert.classList.add(bgStyle)
// 过两秒隐藏
setTimeout(()=>{
myAlert.classList.remove('show')
// 避免类冲突,重置背景色
myAlert.classList.remove(bgStyle)
},2000)
}
document.querySelector('.btn-login').addEventListener('cilck',()=>{
const username=document.querySelector('.username').value
const password=document.querySelector('.password').value
// 1.3判断长度
if(username.length<8){
alertFn('用户名必须大于8位',false)
console.log('用户名必须大于等于8位')
return//组织代码继续执行
}
if(password.length<6){
alertFn('密码必须大于等于6位',false)
console.log('密码必须大于等于6位')
return//阻止代码继续执行
}
//基于axios提交用户名和密码
console.log('提交数据到服务器')
axios({
url:'http://hmajax.itheima.net/api/login',
method:'POST',
data:{
username,
password
}
}).then(result=>{
// console.log(result)
alertFn(result.data.message,true)
console.log(result.data.message)
}).catch(error=>{
console.log(error)
console.log(error.response.data.message)//用户名或密码错误
})
})
form-serialize插件
作用:快速收集表单元素的值
<!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>
<form action="javascript:;" class="example-form">
<input type="text" name="uname">
<br>
<input type="text" name="pwd">
<br>
<input type="button" value="提交" class="btn">
</form>
<!-- 在点击提交时,使用form-serialize插件,快速收集表单元素值
-->
<script src="./lib/form-serialize.js"></script>
<script>
document.querySelector('.btn').addEventListener('click',()=>{
/**
* 使用serialize函数,快速收集表单元素的值
* 参数1:要获取哪个表单的数据
* 表单元素设置name属性 值会作为对象的属性名
* 建议name属性的值,最好和接口文档的参数名一致
* hash 设置获取数据结构
* - true JS对象(true)推荐
* - false 获取查询字符串url?后面传递的参数
* empty 设置是否获取空值
* - true:获取空值 推荐
* - false:不获取空值
* 参数2:配置对象
*/
const form=document.querySelector('.example-form')
// const data=serialize(form,{hash:true,empty:true})
const data=serialize(form,{hash:false,empty:true})
console.log(data)
})
</script>
</body>
</html>
hash:true
hash:false
使用form-serialilze插件获取用户登录中表单里的数据
const form=document.querySelector('.login-form')
const data=serialize(form,{hash:true,empty:true})
const {username,password}=data//解构赋值
// const username = document.querySelector('.username').value
// const password = document.querySelector('.password').value
// console.log(username, password)
Bootstrap弹框的使用
功能:不离开当前页面,显示单独内容,供用户操作
步骤:
- 引入bootstrap.css和bootstrap.js
- 准备弹框标签,确认结构
- 通过自定义属性,控制弹框的显示和隐藏、
通过属性设置,弹框的显示或隐藏(单纯显示和隐藏)
<!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>Bootstrap 弹框</title>
<!-- 引入bootstrap.css -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!--
目标:使用Bootstrap弹框
1. 引入bootstrap.css 和 bootstrap.js
2. 准备弹框标签,确认结构
3. 通过自定义属性,控制弹框的显示和隐藏
-->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target=".my-box">
显示弹框
</button>
<!--
弹框标签
bootstrap的modal弹框,添加modal类名(默认隐藏)
-->
<div class="modal my-box" tabindex="-1">
<div class="modal-dialog">
<!-- 弹框-内容 -->
<div class="modal-content">
<!-- 弹框-头部 -->
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<!-- 弹框-身体 -->
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
<!-- 弹框-底部 -->
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- 引入bootstrap.js -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script>
</body>
</html>
通过JS设置,弹框显示或隐藏(需要额外逻辑代码)
// 1. 创建弹框对象
const modalDom = document.querySelector('.name-box')
const modal = new bootstrap.Modal(modalDom)//得到了和弹框盒子对应的弹框对象
// 编辑姓名->点击->赋予默认姓名->弹框显示
document.querySelector('.edit-btn').addEventListener('click', () => {
document.querySelector('.username').value = '默认姓名'
// 2. 显示弹框
modal.show()
})
// 保存->点击->->获取姓名打印->弹框隐藏
document.querySelector('.save-btn').addEventListener('click', () => {
const username = document.querySelector('.username').value
console.log('模拟把姓名保存到服务器上', username)
// 2. 隐藏弹框
modal.hide()
})
图书管理
自己的图书数据:给自己起个外号,并告诉服务器,默认会有三本书,基于这三本书做数据的增删改查
渲染图书列表
/**
* 目标1:渲染图书列表
* 1.1 获取数据
* 1.2 渲染数据
*/
const creator = '老张'
// 封装-获取并渲染图书列表函数
function getBooksList() {
// 1.1 获取数据
axios({
url: 'http://hmajax.itheima.net/api/books',
params: {
// 外号:获取对应数据
creator
}
}).then(result => {
// console.log(result)
const bookList = result.data.data
console.log(bookList)
// 1.2 渲染数据
const htmlStr = bookList.map((item, index) => {
return `<tr>
<td>${index + 1}</td>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td data-id=${item.id}>
<span class="del">删除</span>
<span class="edit">编辑</span>
</td>
</tr>` //映射到数组的每个元素 并返回修改过的新数组
}).join('')
// console.log(htmlStr)
document.querySelector('.list').innerHTML = htmlStr
})
}
新增图书
/**
* 目标2:新增图书
* 2.1 新增弹框->显示和隐藏
* 2.2 收集表单数据,并提交到服务器保存
* 2.3 刷新图书列表
*/
// 2.1 创建弹框对象
const addModalDom = document.querySelector('.add-modal')
const addModal = new bootstrap.Modal(addModalDom)//利用js代码来隐藏和显示
// 保存按钮->点击->隐藏弹框
document.querySelector('.add-btn').addEventListener('click', () => {
// 2.2 收集表单数据,并提交到服务器保存
const addForm = document.querySelector('.add-form')
const bookObj = serialize(addForm, { hash: true, empty: true })
// console.log(bookObj)
// 提交到服务器
axios({
url: 'http://hmajax.itheima.net/api/books',
method: 'POST',
data: {
...bookObj,//它用于将 bookObj 中的所有可迭代属性展开到新的对象中。这意味着新对象将包含 bookObj 中的所有键值对。
creator
}
}).then(result => {
// console.log(result)
// 2.3 添加成功后,重新请求并渲染图书列表
getBooksList()
// 重置表单
addForm.reset()
// 隐藏弹框
addModal.hide()
})
})
删除图书
/**
* 目标3:删除图书
* 3.1 删除元素绑定点击事件->获取图书id
* 3.2 调用删除接口
* 3.3 刷新图书列表
*/
// 3.1 删除元素->点击(事件委托)
document.querySelector('.list').addEventListener('click', e => {
// 获取触发事件目标元素
// console.log(e.target)
// 判断点击的是删除元素
if (e.target.classList.contains('del')) {
// console.log('点击删除元素')
// 获取图书id(自定义属性id)
const theId = e.target.parentNode.dataset.id
// console.log(theId)
// 3.2 调用删除接口
axios({
url: `http://hmajax.itheima.net/api/books/${theId}`,
method: 'DELETE'
}).then(() => {
// 3.3 刷新图书列表
getBooksList()
})
}
})
编辑图书
/**
* 目标4:编辑图书
* 4.1 编辑弹框->显示和隐藏
* 4.2 获取当前编辑图书数据->回显到编辑表单中
* 4.3 提交保存修改,并刷新列表
*/
// 4.1 编辑弹框->显示和隐藏
const editDom = document.querySelector('.edit-modal')
const editModal = new bootstrap.Modal(editDom)
// 编辑元素->点击->弹框显示
document.querySelector('.list').addEventListener('click', e => {
// 判断点击的是否为编辑元素
if (e.target.classList.contains('edit')) {
// 4.2 获取当前编辑图书数据->回显到编辑表单中
const theId = e.target.parentNode.dataset.id
axios({
url: `http://hmajax.itheima.net/api/books/${theId}`
}).then(result => {
const bookObj = result.data.data
// document.querySelector('.edit-form .bookname').value = bookObj.bookname
// document.querySelector('.edit-form .author').value = bookObj.author
// 数据对象“属性”和标签“类名”一致
// 遍历数据对象,使用属性去获取对应的标签,快速赋值
const keys = Object.keys(bookObj) // ['id', 'bookname', 'author', 'publisher']
keys.forEach(key => {
document.querySelector(`.edit-form .${key}`).value = bookObj[key]
})
})
editModal.show()
}
})
// 修改按钮->点击->隐藏弹框
document.querySelector('.edit-btn').addEventListener('click', () => {
// 4.3 提交保存修改,并刷新列表
const editForm = document.querySelector('.edit-form')
const { id, bookname, author, publisher } = serialize(editForm, { hash: true, empty: true})
// 保存正在编辑的图书id,隐藏起来:无需让用户修改
// <input type="hidden" class="id" name="id" value="84783">
axios({
url: `http://hmajax.itheima.net/api/books/${id}`,
method: 'PUT',//修改
data: {
bookname,
author,
publisher,
creator
}
}).then(() => {
// 修改成功以后,重新获取并刷新列表
getBooksList()
// 隐藏弹框
editModal.hide()
})
})
html代码:
<!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://at.alicdn.com/t/c/font_3736758_vxpb728fcyh.css">
<!-- 引入bootstrap.css -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
<!-- 核心样式 -->
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 主体区域 -->
<div class="container">
<!-- 头部标题和添加按钮 -->
<div class="top">
<h3>图书管理</h3>
<button type="button" class="btn btn-primary plus-btn" data-bs-toggle="modal" data-bs-target=".add-modal"> + 添加
</button>
</div>
<!-- 数据列表 -->
<table class="table">
<thead class="table-light">
<tr>
<th style="width: 150px;">序号</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th style="width: 180px;">操作</th>
</tr>
</thead>
<tbody class="list">
<tr>
<td>1</td>
<td>JavaScript程序设计</td>
<td>马特·弗里斯比</td>
<td>人民邮电出版社</td>
<td>
<span class="del">删除</span>
<span class="edit">编辑</span>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 新增-弹出框 -->
<div class="modal fade add-modal">
<!-- 中间白色区域 -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header top">
<span>添加图书</span>
<button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body form-wrap">
<!-- 新增表单 -->
<form class="add-form">
<div class="mb-3">
<label for="bookname" class="form-label">书名</label>
<input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
</div>
<div class="mb-3">
<label for="author" class="form-label">作者</label>
<input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="form-label">出版社</label>
<input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
</div>
</form>
</div>
<div class="modal-footer btn-group">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 </button>
<button type="button" class="btn btn-primary add-btn"> 保存 </button>
</div>
</div>
</div>
</div>
<!-- 编辑-弹出框 -->
<div class="modal fade edit-modal">
<!-- 中间白色区域 -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header top">
<span>编辑图书</span>
<button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body form-wrap">
<!-- 编辑表单 -->
<form class="edit-form">
<input type="hidden" class="id" name="id">
<div class="mb-3">
<label for="bookname" class="form-label">书名</label>
<input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
</div>
<div class="mb-3">
<label for="author" class="form-label">作者</label>
<input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="form-label">出版社</label>
<input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
</div>
</form>
</div>
<div class="modal-footer btn-group">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 </button>
<button type="button" class="btn btn-primary edit-btn"> 修改 </button>
</div>
</div>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script src="./lib/form-serialize.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.js"></script>
<!-- 核心逻辑 -->
<script src="./js/index.js"></script>
</body>
</html>
图片上传
- 获取图片文件对象
- 使用FormData携带图片文件
- 提交表单数据到服务器,使用图片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>图片上传</title>
</head>
<body>
<!-- 文件选择元素 -->
<input type="file" class="upload">
<img src="" alt="" class="my-img">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/**
* 目标:图片上传,显示到网页上
* 1. 获取图片文件
* 2. 使用 FormData 携带图片文件
* 3. 提交到服务器,获取图片url网址使用
*/
// 文件选择元素->change改变事件
document.querySelector('.upload').addEventListener('change', e => {
// 1. 获取图片文件
console.log(e.target.files[0])
// 2. 使用 FormData 携带图片文件
const fd = new FormData()
fd.append('img', e.target.files[0])
// 3. 提交到服务器,获取图片url网址使用
axios({
url: 'http://hmajax.itheima.net/api/uploadimg',
method: 'POST',
data: fd
}).then(result => {
console.log(result)
// 取出图片url网址,用img标签加载显示
const imgUrl = result.data.data.url
document.querySelector('.my-img').src = imgUrl
})
})
</script>
</body>
</html>
input file类型的change事件
input
元素的file
类型允许用户从他们的设备上选择一个或多个文件。当用户选择了文件(或者修改了已选择的文件)后,change
事件就会被触发。这意味着如果用户通过点击文件输入框并选择了文件,或者拖拽文件到文件输入区域,change
事件监听器就会执行。FormData
FormData
是一个 JavaScript 内建对象,它主要用于构造一组键值对的数据集合,用以发送 HTTP 请求。这个对象特别适用于发送表单数据,无论是作为 AJAX 请求还是使用 Fetch API 发送数据到服务器,尤其是当涉及到文件上传时。以下是关于FormData
的一些关键特点和使用方法:特点:
- 自动构建请求体:
FormData
会根据给定的数据自动构建合适的请求体(Content-Type),这使得它在处理表单数据时非常方便,尤其是当涉及文件上传时,它会正确地设置multipart/form-data
编码。- 兼容性:支持现代浏览器,包括 IE10+,对于旧版浏览器,可能需要polyfill。
- 无需序列化:与传统的
XMLHttpRequest
发送表单数据时需要手动序列化不同,FormData
自动处理这一过程。- 文件上传:非常适合用于文件上传,因为它能够处理二进制数据。
基本用法:
创建实例:
let formData = new FormData();
添加数据:
// 添加文本字段 formData.append('key', 'value'); // 添加文件 let file = document.querySelector('input[type=file]').files[0]; formData.append('file', file); // 添加多个值到同一个键 formData.append('multiValueKey', 'value1'); formData.append('multiValueKey', 'value2');
发送请求:
使用
XMLHttpRequest
或fetch
发送数据:// 使用 XMLHttpRequest let xhr = new XMLHttpRequest(); xhr.open('POST', '/api/upload', true); xhr.send(formData); // 使用 fetch fetch('/api/upload', { method: 'POST', body: formData }) then(response => response.json()) then(data => console.log(data)) catch(error => console.error('Error:', error));
注意事项:
- 当从表单直接创建
FormData
实例时,表单中的所有字段(包括文件输入)会被自动添加到FormData
中。- 可以通过
formData.get(key)
、formData.getAll(key)
、formData.has(key)
、formData.set(key, value)
、formData.delete(key)
等方法来操作数据。- 如果需要获取
FormData
中的所有键值对,可以使用formData.entries()
方法配合迭代器遍历。
FormData
是处理表单数据和文件上传的强大工具,极大地简化了从前复杂的 AJAX 请求处理过程。
更换网页背景图片
1.选择图片上传,设置body背景
2.上传成功时,保存url网址
3.网页运行后,获取url网址使用
/**
* 目标:网站-更换背景
* 1. 选择图片上传,设置body背景
* 2. 上传成功时,"保存"图片url网址
* 3. 网页运行后,"获取"url网址使用
* */
//选择对应的input框绑定change事件
document.querySelector('.bg-ipt').addEventListener('change', e => {
// 1. 选择图片上传,设置body背景
console.log(e.target.files[0])
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 => {
const imgUrl = result.data.data.url
document.body.style.backgroundImage = `url(${imgUrl})`
// 2. 上传成功时,"保存"图片url网址
localStorage.setItem('bgImg', imgUrl)
})
})
// 3. 网页运行后,"获取"url网址使用
const bgUrl = localStorage.getItem('bgImg')
console.log(bgUrl)
// 本地有背景图才设置
bgUrl && (document.body.style.backgroundImage = `url(${bgUrl})`)
个人信息设置
步骤:
1.信息渲染
2.头像修改
3.提交表单
4.结果提示
信息渲染
自己的用户信息:给自己起个外号,并告诉服务器,获取对应的用户信息
/**
* 目标1:信息渲染
* 1.1 获取用户的数据
* 1.2 回显数据到标签上
* */
const creator = '播仔'
// 1.1 获取用户的数据
axios({
url: 'http://hmajax.itheima.net/api/settings',
params: {
creator
}
}).then(result => {
const userObj = result.data.data
// 1.2 回显数据到标签上
Object.keys(userObj).forEach(key => {
if (key === 'avatar') {
// 赋予默认头像
document.querySelector('.prew').src = userObj[key]
} else if (key === 'gender') {//gender和头像不可通过value来改变,只有表单元素才可通过foreach来改变
// 赋予默认性别
// 获取性别单选框:[男radio元素,女radio元素]
const gRadioList = document.querySelectorAll('.gender')
// 获取性别数字:0男,1女
const gNum = userObj[key]
// 通过性别数字,作为下标,找到对应性别单选框,设置选中状态
gRadioList[gNum].checked = true
} else {
// 赋予默认内容
document.querySelector(`.${key}`).value = userObj[key]
}
})
})
头像修改
/**
* 目标2:修改头像
* 2.1 获取头像文件
* 2.2 提交服务器并更新头像
* */
// 文件选择元素->change事件
document.querySelector('.upload').addEventListener('change', e => {
// 2.1 获取头像文件
console.log(e.target.files[0])
const fd = new FormData()
fd.append('avatar', e.target.files[0])
fd.append('creator', creator)
// 2.2 提交服务器并更新头像
axios({
url: 'http://hmajax.itheima.net/api/avatar',
method: 'PUT',
data: fd
}).then(result => {
const imgUrl = result.data.data.avatar
// 把新的头像回显到页面上
document.querySelector('.prew').src = imgUrl
})
})
提交表单(信息修改)
结果提示
给div盒子添加类名toast,会出现提示框
/**
* 目标4:结果提示
* 4.1 创建toast对象
* 4.2 调用show方法->显示提示框
*/
// 保存修改->点击
document.querySelector('.submit').addEventListener('click', () => {
// 3.1 收集表单信息
const userForm = document.querySelector('.user-form')
const userObj = serialize(userForm, { hash: true, empty: true })
userObj.creator = creator
// 性别数字字符串,转成数字类型
userObj.gender = +userObj.gender
console.log(userObj)
// 3.2 提交到服务器保存
axios({
url: 'http://hmajax.itheima.net/api/settings',
method: 'PUT',
data: userObj//aixos会自动将对象转化为JSON字符串
}).then(result => {
// 4.1 创建toast对象
const toastDom = document.querySelector('.my-toast')
const toast = new bootstrap.Toast(toastDom)
// 4.2 调用show方法->显示提示框
toast.show()
})
})
AJAX原理 - XMLHttpRequest
定义:XMLHttpRequest(XHR)对象用于与服务器进行交互,通过XMLHttpRequest可以在不刷新页面的情况下请求特定URL,获取数据,这允许网页在不影响用户操作的情况下,更新页面的局部内容,XMLHttpRequest在AJAX编程中被大量使用
关系:axios内部采用XMLHttpRequest与服务器进行交互
好处:掌握使用XHR与服务器进行数据交互,了解axios内部原理
使用XMLHttpRequest
需求:获取并展示所有省份名字
/**
* 目标:使用XMLHttpRequest对象与服务器通信
* 1. 创建 XMLHttpRequest 对象
* 2. 配置请求方法和请求 url 地址
* 3. 监听 loadend 事件,接收响应结果
* 4. 发起请求
*/
// 1. 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest()
// 2. 配置请求方法和请求 url 地址
xhr.open('GET', 'http://hmajax.itheima.net/api/province')
// 3. 监听 loadend 事件,接收响应结果,loadend无论成功还是失败,都会执行后面的函数
xhr.addEventListener('loadend', () => {
console.log(xhr.response)
const data = JSON.parse(xhr.response)
console.log(data.list.join('<br>'))
document.querySelector('.my-p').innerHTML = data.list.join('<br>')
})
// 4. 发起请求
xhr.send()
XHR使用步骤:
- 创建XHR对象
- 调用open方法,设置url和请求方法
- 监听loadend事件,接收结果
- 调用send方法,发起请求
XMLHttpRequest- 查询参数
定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
/**
* 目标:使用XHR携带查询参数,展示某个省下属的城市列表
*/
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://hmajax.itheima.net/api/city?pname=辽宁省')
xhr.addEventListener('loadend', () => {
console.log(xhr.response)
const data = JSON.parse(xhr.response)
console.log(data)
document.querySelector('.city-p').innerHTML = data.list.join('<br>')
})
xhr.send()
地区查询
需求:输入省份和城市名字,查询地区列表
请求地址:http://hmajax.itheima.net/api/area?参数名=值1&参数名=值2
/**
* 目标: 根据省份和城市名字, 查询对应的地区列表
*/
// 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()
})
XMLHttpRequest - 数据提交
需求:通过XHR提交用户名和密码,完成注册功能
核心:
- 请求头设置Content - Type:application/json
- 请求体携带JSON字符串
<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>