1.渲染列表
自己的图书数据:给自己起个外号,并告诉服务器,默认会有三本书,基于这三本书做数据的增删改查。
// 目标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.dataconsole.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><span class="del">删除</span><span class="edit">编辑</span></td></tr>`}).join('')console.log(htmlStr)document.querySelector('.list').innerHTML = htmlStr})
}
// 网页加载运行,获取并渲染列表一次
getBooksList()
2.新增图书
/*** 目标2:新增图书* 2.1 新增弹框 -> 显示和隐藏* 2.2 收集表达数据,并提交到服务器保存* 2.3 刷新图书列表*/// 2.1 创建弹框对象
const addModalDom = document.querySelector('.add-modal')
const addModal = new bootstrap.Modal(addModalDom)
// 保存按钮 -> 点击 -> 隐藏弹框
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,creator}}).then(result => {console.log(result)// 2.3 添加成功后,重新请求并渲染图书列表getBooksList()// 重置表单addForm.reset()// 隐藏弹框addModal.hide()})})
3.删除图书
/*** 目标3: 删除图书* 3.1 删除元素绑定点击事件 -> 获取图书* 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.idconsole.log(theId)// 3.2 调用删除接口axios({url: `http://hmajax.itheima.net/api/books/${theId}`,method:'DELETE'}).then(() => {//3.3 刷新图书列表getBooksList()})}
})
4.编辑图书
/*** 目标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// console.log(theId)axios({url: `http://hmajax.itheima.net/api/books/${theId}`}).then(result => {// console.log(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']// console.log(keys)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})// console.log(bookObj)// 保存正在编辑的图书id,隐藏起来,无需让用户修改//<input type="hidden" class="id" name="id" value="385168">axios({url: `http://hmajax.itheima.net/api/books/${id}`,method: 'PUT',data: {bookname,author,publisher,creator}}).then(() => {// 修改成功以后,重新获取并刷新列表getBooksList()// 隐藏弹框editModal.hide()})})
index.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>
index.css
/* 公共*/
html,
body {width: 100%;height: 100%;
}.container {width: 1340px;margin: 0 auto;padding-top: 60px;box-sizing: border-box;
}/* alert提示框 */
.toast {position: fixed;top: 20px;left: 50%;transform: translateX(-50%);
}.toast .toast-body {padding: 0 !important;
}.toast .alert-success {margin-bottom: 0 !important;
}/* 头部导航 */
.container .top {display: flex;justify-content: space-between;
}.container .top h3 {font-weight: 900;
}.container .top .plus-btn {background-color: #539ACB !important;color: #fff;border: none;
}/* 表格部分 */
.table {margin-top: 20px;text-align: center;font-size: 14px;
}.table-light th {background-color: #939CA7 !important;color: #ffffff;font-family: PingFangSC-Medium;font-size: 16px;text-align: center;font-weight: 500;border-right: 1px solid lightgray;
}.table-light th:last-of-type {border-right: none;
}/* 表格内容 */
.table tbody td {color: #696F77;
}.table .del {color: #E5964C;margin-right: 30px;
}.table .edit {color: #539ACB;
}.table tbody tr {height: 30px;line-height: 30px;
}.table tbody tr td:last-of-type span {cursor: pointer;
}/* 弹出层 */
.modal .top {display: flex;justify-content: center;background-color: #F0F3F7;padding: 15px 0;width: 100%;position: relative;color: #1E2023;
}/* 右上角-关闭按钮 */
.modal .btn-close {font-size: 12px;position: absolute;top: 50%;transform: translateY(-50%);right: 23px;/* 覆盖bootstrap样式 */margin: 0;padding: 0;
}/* 表单容器 */
.form-wrap {box-sizing: border-box;background-color: white;padding: 40px;
}.form-wrap .form-label {color: #696F77;
}/* 修改输入框默认占位文字webkit内核, firefox18-, firfox19+, 其他*/
.form-wrap input::-webkit-input-placeholder {color: #BFBFBF !important;font-size: 14px;
}/* 底部按钮组 */
.modal-footer{border-top: 0;
}
.btn-group {text-align: center;width: 100%;
}/* 修改bs的按钮弹性布局-改成自己设置大小 */
.btn-group,
.btn-group-vertical {display: block;
}.btn-group button {width: 120px
}.btn-group button:first-of-type {border: 1px solid #E3E3E3;background-color: #fff;color: black;margin-right: 60px;
}.btn-group button:last-of-type {background-color: #539ACB;
}.alert-success {border-color: transparent;
}.toast {border: none;
}