AJAX——图书管理案例

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.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>
              <span class="del">删除</span>
              <span class="edit">编辑</span>
            </td>
          </tr>
            `
        }).join('')
       console.log(htmlStr)
       document.querySelector('.list').innerHTML = htmlStr
    })
}
// 网页加载运行,获取并渲染列表一次
getBooksList()

2.新增图书

javascript 复制代码
/**
 * 目标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.删除图书

javascript 复制代码
/**
 * 目标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.id
    console.log(theId)
    // 3.2 调用删除接口
    axios({
        url: `http://hmajax.itheima.net/api/books/${theId}`,
        method:'DELETE'
    }).then(() => {
        //3.3 刷新图书列表
        getBooksList()
    })
  }
})

4.编辑图书

javascript 复制代码
/**
 * 目标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代码

javascript 复制代码
<!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;
}
相关推荐
2401_882727572 分钟前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
会发光的猪。36 分钟前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客1 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记1 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
前端李易安1 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js
红绿鲤鱼1 小时前
React-自定义Hook与逻辑共享
前端·react.js·前端框架
Domain-zhuo2 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
小丁爱养花2 小时前
前端三剑客(三):JavaScript
开发语言·前端·javascript
ZwaterZ2 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue
码农六六2 小时前
vue3封装Element Plus table表格组件
javascript·vue.js·elementui