持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
Ajax 提交表单数据的用法
表单的组成
网页中采集数据的表单由三个部分组成,分别是:表单标签(form)、表单域(input、textarea、select)、表单按钮(submit或者reset)。
表单的作用就是收集数据。
表单的提交事件和阻止默认行为
$('form').on('submit', function (e) {
e.preventDefault();
})
jQuery 的 serialize()函数
$('form').serialize() 获取到的form表单数据类型为 a=1&b=2&c=3 可以直接发送给服务器使用
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3009/api/form',
data: $('form').serialize() // 获取所有参数,类型: a=1&b=2&c=3
}).then(({ data: res }) => {
console.log(res)
})
注意: 表单标签必须带有 name 属性;
axios请求方法别名
为了简化开发者的使用过程,axios 为所有支持的请求方法提供了别名:
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
<!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">删除</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>
<!-- 引入 lib 目录下的 jQuery 和 axios -->
<script src="./lib/jquery-v3.6.0.js"></script>
<script src="./lib/axios.js"></script>
<script>
//入口函数
$(function () {
//设置全局路径
axios.defaults.baseURL = 'http://www.liulongbin.top:3009'
//请求并渲染图书列表的数据
//把渲染图书列表封装成函数 添加和删除完毕也要重新渲染最新数据
function renderBookList() {
//发送ajax
axios.get('/api/getbooks').then(({ data: res }) => {
//判断页面状态码
if (res.code != 200) {
return alert(res.msg)
}
//成功就渲染 map() forEach()
let arr = res.data.map(item => {
return `
<tr>
<th scope="row">${item.id}</th>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td>
<button type="button" data-id="${item.id}" class="btn-delete btn-link btn-sm">删除</button>
</td>
</tr>
`
})
//赋值 要写在map()外面 .then()回调函数里面
tbody.innerHTML = arr.join('')
})
}
//页面加载时渲染图书列表
let tbody = document.querySelector('tbody')
renderBookList()
//添加图书 绑定提交事件 阻止默认提交
const addForm = document.querySelector('#addForm')
addForm.addEventListener('submit', function (e) {
//阻止默认提交
e.preventDefault()
//发送ajax post/put/patch() 第二个参数直接就是请求参数体
axios.post('/api/addbook', $(this).serialize()).then(({ data: res }) => {
//判断业务状态码
if (res.code != 201) {
return alert(res.msg)
}
//成功提示 清空表单 重新渲染页面
alert('恭喜你,添加图书成功')
//reset()可以触发reset事件,触发重置表单(类似focus())
//因为用的是箭头函数 没有自己的this 指向外层很熟的this所以使用addForm和
addForm.resst()
renderBookList()
})
})
//删除图书 事件委托绑定
tbody.addEventListener('click', function (e) {
//判断点击的是否是button按钮
//classList.contains()判断是否包含某个类名
//优化 if(!e.target.classList.contains('btn-delete')) return
if (e.target.classList.contains('btn-delete') == false) {
return
}
//获取自定义属性
const id = e.target.dataset.id
console.log(id);
//发送ajax 删除图书
axios.delete('/api/delbook', {
//delete传递查询参数 需要使用par
params: { id }
}).then(({ data: res }) => {
//判断业务状态码
if (res.code != 200) {
//如果删除失败 重新渲染页面
renderBookList()
return alert(res.msg)
}
//成功提示 重新渲染页面
alert('恭喜你删除成功')
renderBookList()
})
})
})
</script>
</body>
</html>
axios 拦截器的用法
axios 拦截器
拦截器(interceptors)用来全局拦截 axios 的每一次请求与响应。
好处:可以把每个请求中,某些重复性的业务代码封装到拦截器中,提高代码的复用性。
axios 请求拦截器
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
注意:一部分请求拦截器因为所有请求,无须逻辑判断,都要执行操作,所以记性了全局的 axios 默认值
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios 响应拦截器
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
文件上传
FormData的概念
概念:FormData 是浏览器提供的一个 WebAPI,它以键值对的方式存储数据。 作用:FormData 配合 Ajax 技术,能够向服务器发送 multipart/form-data 格式的请求体数据。 场景:FormData + Ajax 技术实现文件上传的功能。 注意:Ajax 实现文件上传的时候,请求体的编码格式必须是 multipart/form-data。
基本用法
FormData 是一个构造函数,new FormData() 即可得到 FormData 对象:
const fd = new FormData() // 创建一个空白的 FormData 对象,里面没有包含任何数据。
调用 FormData 对象的 append(键, 值) 方法,可以向空白的 FormData 中追加键值对数据,其中:
// 键表示数据项的名字,必须是字符串
// 值表示数据项的值,可以是任意类型的数据
fd.append('username', '张三') // 键是 username,值是字符串类型
fd.append('age', 20) // 键是 age, 值是数字类型
fd.append('avatar', 图片文件) // 键是 avatar, 值是文件类型
发送普通的 FormData 数据
// 创建
const fd = new FormData() ;
// 添加
fd.append('username', '张三') // 键是 username,值是字符串类型
fd.append('age', 20) // 键是 age, 值是数字类型
fd.append('avatar', 图片文件) // 键是 avatar, 值是文件类型
// 使用
$('#btn').on('click', function (){
axios.post('http://www.liulongbin.top:3006/api/formdata', fd).then(({data: res}) => {
console.log(res);
});
})
头像上传
<!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/jquery-v3.6.0.js"></script>
<script src="./lib/axios.js"></script>
<script>
// 需求1: 点击button,触发input的点击事件;
const img = document.querySelector('img');
const inp = document.querySelector('input');
const btn = document.querySelector('button');
// 绑定事件
btn.addEventListener('click', function () {
inp.click();
});
// 需求2: 选择图片,触发事件,发送ajax,实现文件上传;
// 选择图片,触发事件 - change (value值发生改变)
// 给inp绑定change事件;
inp.addEventListener('change', function () {
// 创建 FormData 对象,添加进去file对象
const fd = new FormData();
// input标签对象上有一个属性files,里面放入选择的文件对象,是一个伪数组;
fd.append('avatar', inp.files[0]);
// 发送ajax
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3009/api/upload/avatar',
// 传递请求体参数,data属性
data: fd
}).then(({ data: res }) => {
// 判断业务状态码
if (res.code != 200) {
return alert(res.message);
}
// 成功提示
alert('恭喜您,上传头像成功!');
// 成功重新渲染图片
img.src = 'http://www.liulongbin.top:3009' + res.url;
});
})
</script>
</body>
</html>
最后是原图😍