目录
form 表单 & 文件上传
1.掌握 Ajax 提交表单数据的用法
能够在实际项目开发中通过 axios 提交表单的数据
2.掌握 FormData 的使用
能够使用 FormData 结合 axios 实现文件上传功能
Form表单
表单是什么?
在网页中表单主要负责数据采集功能
表单的三个组成部分
1、表单标签<form>:一个容器,用来将页面上指定的区域划定为表单区域
一、自动采集用户所有信息
二、自动提交数据
三、<form>标签属性{1、action:指定提交的url地址 2、method:指定提交方式,默认方式为GET}
2、表单域:提供给用户书写数据采集用户信息的渠道,常见的表单域有:input、textarea、select等,(必须包含name属性,否则用户填写的信息无法被采集到)
表单提交的问题
1、自动跳转页面
2、产生问题的原因{既负责采集数据,有负责把数据提交到服务器,表单的默认行为会导致页面的跳转}
解决方案
1、表单只负责采集数据(符合职能单一的原则)
2、ajax负责将数据提交到服务器
{1、可以防止表单默认提交行为导致的页面跳转问题,提高用户的体验
2、form-serialize 序列化得到表单数据
serialize(form)--> string
serialize(form, {hash: true}) --> object}
文件上传
FormData
概念:FormData是浏览器提供的一个WebAPI,它以键值的方式存储数据;是一个构造函数,new FormData即可得到FormData对象
应用场景:FormData + Ajax 技术实现文件上传功能
处理文件数据:const fd = new FormData()
数据来源
input:file
【1、change:获取改变文件数据 文件的参数
2、ipt.files[0]】
数据来源
【1、change:获取改变文件数据文件的参数2、ipt.files[0]】
将数据存储在fd
【1、fd.append("键", 值) 2、键表示数据项的名字,必须是字符串;值表示数据项的值,任意类型】
发送到服务器
axios
案例-头像上传
<!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="./lib/bootstrap-v4.6.0.css">
<style>
.thumb-box {
text-align: center;
margin-top: 50px;
}
.thumb {
width: 250px;
height: 250px;
object-fit: cover;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="thumb-box">
<!-- 头像 -->
<img src="./images/cover.jpg" class="img-thumbnail thumb" alt="">
<div class="mt-2">
<!-- 文件选择框 -->
<!-- accept 属性表示可选择的文件类型 -->
<!-- image/* 表示只允许选择图片类型的文件 -->
<input type="file" id="iptFile" accept="image/*" style="display: none;">
<!-- 选择头像图片的按钮 -->
<button class="btn btn-primary" id="btnChoose">选择 & 上传图片</button>
</div>
</div>
<script src="./lib/axios.js"></script>
<script>
// 在线接口文档:https://www.showdoc.com.cn/ajaxapi/3754974183518732
let btnChoose = document.querySelector('#btnChoose')
let iptFile = document.querySelector('#iptFile')
let img = document.querySelector('.thumb')
// 功能
// 1. 点击按钮,弹出文件选择框
// 1.1 给用户点击的按钮注册事件
btnChoose.addEventListener('click', function() {
//1.2调出 选择文件的 选择框
// 如果要调出选择框 只能通过 type 类型为file的input点击才能触发
iptFile.click()
})
// 2. 实现文件的上传功能
//2.1 绑定change事件
iptFile.addEventListener('change', function() {
// 2.2 实例化formData数据
const fd = new FormData()
// 2.3 获取文件参数
console.log(this.files[0]);
// 2.4 将数据保存在formData中
fd.append('avatar', this.files[0])
// 2.5 将数据 上传
axios({
method: 'POST',
url:'http://www.liulongbin.top:3006/api/upload/avatar',
data: fd
}).then(({data:res}) =>{
console.log(res);
// 2.6 根据上传结果执行对相应的操作
if(res.status === 200) {
img.src = `http://www.liulongbin.top:3006${res.url}`
}else{
alert(res.message)
}
})
})
</script>
</body>
</html>
请求体类型(Content-Type)
application
【1、 x-www-form-urlencoded:普通字符串,表单中不包含文件上传的场景,适用于普通数据的提交
2、 json:JSON字符串,上传json格式数据】
multipart/form-data
二进制文件,表单中包含上传文件的场景
不同的数据类型对应不同的请求类型,axios默认帮我们做了设置处理
案例-图书管理
<!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>
<!-- 引入 lib 目录下的 bootstrap 样式表 -->
<link rel="stylesheet" href="./lib/bootstrap-v4.6.0.css">
<style>
:root {
font-size: 15px;
}
body {
padding-top: 15px;
}
</style>
</head>
<body>
<!-- 栅格系统 -->
<div class="container-fluid">
<!-- 栅格系统中的一行 -->
<div class="row">
<!-- 左侧的表格,占了 8 列 -->
<div class="col-sm-8">
<table class="table table-bordered table-striped table-dark table-hover text-center">
<thead>
<!-- 表头行 -->
<tr>
<th scope="col">Id</th>
<th scope="col">书名</th>
<th scope="col">作者</th>
<th scope="col">出版社</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<!-- 表格中的每一行 -->
<tr>
<th scope="row">xxx</th>
<td>xxx</td>
<td>xxx</td>
<td>xxx</td>
<td>
<button type="button" class="btn btn-link btn-sm btn-del">删除</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 右侧的添加区域,占了 4 列 -->
<div class="col-sm-4">
<!-- 添加图书的卡片 -->
<div class="card text-white bg-secondary sticky-top">
<div class="card-header">添加新图书</div>
<form class="card-body bg-light" id="addForm">
<!-- 书名 -->
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">书名</span>
</div>
<input type="text" class="form-control" placeholder="请输入图书名称" name="bookname">
</div>
<!-- 作者 -->
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">作者</span>
</div>
<input type="text" class="form-control" placeholder="请输入作者名字" name="author">
</div>
<!-- 出版社 -->
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">出版社</span>
</div>
<input type="text" class="form-control" placeholder="请输入出版社名称" name="publisher">
</div>
<!-- 添加按钮 -->
<button class="btn btn-dark" type="submit">添加</button>
</form>
</div>
</div>
</div>
</div>
<script src="./lib/form-serialize.js"></script>
<script src="./lib/axios.js"></script>
<script>
// 功能
// 1. 渲染数据
// 1.1获取参与功能的标签
const tbody = document.querySelector('tbody')
const btn = document.querySelector('#addForm button')
const addForm = document.querySelector('#addForm')
// 1.2 发请求 拿数据
function render() {
axios({
mothod: 'GET',
url:'http://www.liulongbin.top:3006/api/getbooks',
}).then(({data:res}) => {
//1.3获取数据
console.log(res);
//1.4根据对应的结果执行对应的操作
if(res.status === 200){
// 渲染列表
// 1.5将数据处理成对应的HTML标签
const str = res.data.map((item, i) =>{
const {id, bookname, author, publisher} = item
return `
<tr>
<th scope="row">${id}</th>
<td>${bookname}</td>
<td>${author}</td>
<td>${publisher}</td>
<td>
<button type="button" class="btn btn-link btn-sm btn-del" data-id='${id}'>删除</button>
</td>
</tr>
`
}).join('')
// console.log(str);
// 将处理好的解构添加到对应位置
tbody.innerHTML = str
} else{
alert(res.msg)
}
})
}
render()
// 2. 添加数据
// 2.1绑定事件
btn.addEventListener('click', function(e) {
// 2.3解决默认行为
e.preventDefault()
// 2.2 获取数据
const data = serialize(addForm, {hash: true})
console.log(data);
// 2.4将数据添加到服务器
axios({
method:'POST',
url:'http://www.liulongbin.top:3006/api/addbook',
data
}).then(({data:res}) =>{
// console.log(res);
// 2.5根据返回的结果执行对应的操作
if(res.status === 201) {
render()
// 2.6清空
addForm.reset()
}else{
alert(res.msg)
}
})
})
// 3. 删除数据
tbody.addEventListener('click', function(e) {
// 3.1 只有点击删除按钮的时候才执行操作
// e.target.tagName = 'BUTTON'
if(e.target.classList.contains('btn-del')) {
// console.log(111);
// console.log(e.target.dataset.id);
const id = +e.target.dataset.id
// 3.3删除数据库数据
axios({
method:'DELETE',
url:'http://www.liulongbin.top:3006/api/delbook',
params:{
id
}
}).then(({data:res}) =>{
// 3.4获取
// console.log(res);
if(res.status === 201) {
} else{
alert(res.msg )
}
})
}
})
</script>
</body>
</html>
axios请求方法的别名
1、axios.get(url[,config])
【1、 中括号里的可省略不写
2、axios.get(地址,配置项目)
3、配置项看axios官方文档】
2、axios.delete(url[, config])
axios.delete('url地址', {params: {id}}) 根据id删除数据
3、axios.post(url[, data[, config]])
【 1、 axios.post(地址, data, 配置项)
2、data 请求体里边的键值对看接口文档,配置项看axios官方文档】
4、axios.put(url[, data[, config]])
5、axios.patch(url[, data[, config]])
6、axios官方文档:http://www.axios-js.com/zh-cn/docs/ 全局配置根目录 axios.defaults.baseURL = ‘ ’