Ajax基础入门(day2) - form表单 & 文件上传

Ajax基础入门(day2) - form表单 & 文件上传_第1张图片

文章目录

  • 参考接口文档
  • 一、form 表单
    • 1. 什么是表单
    • 2. 表单的三个组成部分
    • 3.
      标签的属性一览表
    • 4. 以 GET 方式提交表单数据
    • 5. 以 POST 方式提交表单数据
    • 6. 通过 Ajax 提交表单数据
      • 细节:阻止默认提交行为
      • form-serialize 序列化得到表单数据
  • 二、文件上传
    • 1. FormData
    • 2. 案例 - 头像上传
    • 3. 请求体类型 Content-Type
  • 三、案例 - 图书管理
    • 1. 请求并渲染图书列表的数据
    • 2. 添加图书
    • 3. 删除图书
    • 学会如何查明 bug
      • 忘记携带参数了
      • 忘记用自定义属性存 id
  • 四、axios 请求方法的别名
    • 1. 什么是请求方法的别名
    • 2. 体验 axios.get() 的用法
    • 3. 体验 axios.post() 的用法
      • 一个知识点:
    • 4. 全局配置请求根路径
    • 简化改写:图书管理案例
  • 五、总结

参考接口文档

我们的学习过程中需要参考一篇接口文档
点击进入接口文档

一、form 表单

1. 什么是表单

Ajax基础入门(day2) - form表单 & 文件上传_第2张图片

2. 表单的三个组成部分

Ajax基础入门(day2) - form表单 & 文件上传_第3张图片

Ajax基础入门(day2) - form表单 & 文件上传_第4张图片

Ajax基础入门(day2) - form表单 & 文件上传_第5张图片

Ajax基础入门(day2) - form表单 & 文件上传_第6张图片

Ajax基础入门(day2) - form表单 & 文件上传_第7张图片

Ajax基础入门(day2) - form表单 & 文件上传_第8张图片

3. 标签的属性一览表

Ajax基础入门(day2) - form表单 & 文件上传_第9张图片

4. 以 GET 方式提交表单数据

Ajax基础入门(day2) - form表单 & 文件上传_第10张图片
GET 提交表单数据有个缺陷,就是我们用户的密码会直接显示在地址里
Ajax基础入门(day2) - form表单 & 文件上传_第11张图片

5. 以 POST 方式提交表单数据

我们选用更加安全的提交方式: POST 方式
Ajax基础入门(day2) - form表单 & 文件上传_第12张图片
Ajax基础入门(day2) - form表单 & 文件上传_第13张图片

Ajax基础入门(day2) - form表单 & 文件上传_第14张图片

Ajax基础入门(day2) - form表单 & 文件上传_第15张图片

Ajax基础入门(day2) - form表单 & 文件上传_第16张图片

6. 通过 Ajax 提交表单数据

细节:阻止默认提交行为

Ajax基础入门(day2) - form表单 & 文件上传_第17张图片

<!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>
  <link rel="stylesheet" href="./css/bootstrap.min.css" />
  <link rel="stylesheet" href="./css/login.css" />
</head>

<body>
  <div class="login-box">
    <form>
      <div class="form-group mb-3">
        <label for="username">Account</label>
        <!-- 账号 -->
        <input type="text" class="form-control" name="username" id="username" autocomplete="off" />
        <small id="emailHelp" class="form-text text-muted">The available account is <strong>admin</strong></small>
      </div>
      <div class="form-group mb-3">
        <!-- 密码 -->
        <label for="password">Password</label>
        <input type="password" class="form-control" name="password" id="password" />
        <small id="emailHelp" class="form-text text-muted">The available password is <strong>123456</strong></small>
      </div>
      <button type="submit" class="btn btn-primary" id="btnLogin">Submit</button>
    </form>
  </div>

  <script src="./lib/axios.js"></script>
  <script>
    // 请求方式 POST
    // 地址 http://www.liulongbin.top:3009/api/login
    // 参数:  username 用户名     password  密码

    // 使用Ajax提交表单数据的步骤
    //  1. 监听表单的 submit 提交事件  ==> 当表单提交的时候会触发submit事件
    //  2. 阻止默认提交行为     ==> e.preventDefault()
    //  3. 基于 axios 发起请求
    //  4. 指定请求方式、请求地址、指定请求体数据

    // 1. 
    document.querySelector('form').addEventListener('submit', function (e) {
      // 2. 阻止默认的提交行为
      e.preventDefault()

      // 提交的时候,来获取
      let username = document.querySelector('#username').value
      let password = document.querySelector('#password').value

      // 3. 
      axios({
        method: 'post',
        url: 'http://www.liulongbin.top:3009/api/login',
        data: {
          username,
          password
        }
      }).then(({ data: res }) => {
        console.log(res)
      })
    })
  </script>
</body>

</html>

form-serialize 序列化得到表单数据

Ajax基础入门(day2) - form表单 & 文件上传_第18张图片

<!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>
  <link rel="stylesheet" href="./css/bootstrap.min.css" />
  <link rel="stylesheet" href="./css/login.css" />
</head>

<body>
  <div class="login-box">
    <form>
      <div class="form-group mb-3">
        <label for="username">Account</label>
        <!-- 账号 -->
        <input type="text" class="form-control" name="username" id="username" autocomplete="off" />
        <small id="emailHelp" class="form-text text-muted">The available account is <strong>admin</strong></small>
      </div>
      <div class="form-group mb-3">
        <!-- 密码 -->
        <label for="password">Password</label>
        <input type="password" class="form-control" name="password" id="password" />
        <small id="emailHelp" class="form-text text-muted">The available password is <strong>123456</strong></small>
      </div>
      <button type="submit" class="btn btn-primary" id="btnLogin">Submit</button>
    </form>
  </div>

  <script src="./lib/axios.js"></script>
  <script src="./lib/form-serialize.js"></script>

  <script>
    // 请求方式 POST
    // 地址 http://www.liulongbin.top:3009/api/login
    // 参数:  username 用户名     password  密码

    // 使用Ajax提交表单数据的步骤
    //  1. 监听表单的 submit 提交事件
    //  2. 阻止默认提交行为
    //  3. 基于 axios 发起请求
    //  4. 指定请求方式、请求地址、指定请求体数据

    // 引入form-serialize插件,提供 serialize 函数,从而获取表单数据
    // serialize(form表单的DOM对象)

    // let form = document.querySelector('form')

    // 都可以获取到表单数据
    // serialize(form)  // 'username=admin&password=123456'
    // serialize(form, { hash: true })  // js对象 {username: 'admin', password: '123456'}


    document.querySelector('form').addEventListener('submit', function (e) {
      // 2. 阻止默认的提交行为
      e.preventDefault()

      // 提交的时候,serialize插件来获取表单数据
      let data = serialize(this, {    // this 指向了事件源
        // {} 配置对象 hash 配置,可以将 收集到的表单数据是个js对象格式
        hash: true
      })
      console.log(data)

      // 3. 
      axios({
        method: 'post',
        url: 'http://www.liulongbin.top:3009/api/login',
        // 这个data不能省,否则没有提交数据给服务器
        data
      }).then(({ data: res }) => {
        console.log(res)
      })
    })
  </script>
</body>

</html>

小结复习:
Ajax基础入门(day2) - form表单 & 文件上传_第19张图片


二、文件上传

1. FormData

Ajax基础入门(day2) - form表单 & 文件上传_第20张图片

Ajax基础入门(day2) - form表单 & 文件上传_第21张图片

测试:
Ajax基础入门(day2) - form表单 & 文件上传_第22张图片

Ajax基础入门(day2) - form表单 & 文件上传_第23张图片

2. 案例 - 头像上传

Ajax基础入门(day2) - form表单 & 文件上传_第24张图片

在这里插入图片描述

Ajax基础入门(day2) - form表单 & 文件上传_第25张图片

测试:
Ajax基础入门(day2) - form表单 & 文件上传_第26张图片

Ajax基础入门(day2) - form表单 & 文件上传_第27张图片

上传到服务器后可以自行检查一下,复制根路径http://www.liulongbin.top:3006加上浏览器终端中的 url 地址:/uploads/1661265302836_7e9cb873e5564c9d9cc5dd66a59fd101.jpg到浏览器进行访问,就可以看到我们刚上传的图片。
了解清楚如何得到这个图片的地址后,后面实现头像的更换就简单了
Ajax基础入门(day2) - form表单 & 文件上传_第28张图片

编写更换头像的功能
Ajax基础入门(day2) - form表单 & 文件上传_第29张图片

随后我们发现一个问题,就是如果点击按钮打开选择头像文件弹窗,但是我们不选择头像直接点击打开的话,会报错:
在这里插入图片描述
业务响应码为 502,代表它为 502 时我们并没有上传头像,所以要对代码进行优化。
Ajax基础入门(day2) - form表单 & 文件上传_第30张图片
最终代码:

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">
      
      
      
      <input type="file" id="iptFile" accept="image/*" style="display: block;">
      
      <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. 点击按钮,弹出文件选择框  ==> 模拟点击文件选择器,从而实现弹框来选择文件
    // 给按钮添加点击事件,按钮被点击后模拟点击一次 iptFile 实现 选择弹窗
    btnChoose.addEventListener('click',function(){
        iptFile.click()
    })
   
    //  2. 实现文件的上传功能
    // FormData 存文件  === axios 发请求(看接口文档)

    iptFile.addEventListener('change', function(){
        console.log(this.files[0])

        // 当 this.files[0] 是 undefined 时,表示用户没有选中文件,以下代码不执行
        if(!this.files[0]){   // undefined是false,!false 就是 ture。if(true)则执行return 终止后续代码的执行
            alert('未选择任何文件,请重新上传')
            return 
        }

        let fd = new FormData() 
        // 接口文档要求了,参数名得是 avatar
        fd.append('avatar', this.files[0])
        // 上传到服务器
        axios({
            method: 'post',
            // 请求的 url 地址一定要从接口文档中去复制
            url: 'http://www.liulongbin.top:3006/api/upload/avatar',
            // data 的值是 fd(把FormData存的数据给发送到服务器上)
            data: fd
        }).then(({data: res}) => {
            console.log(res)
            console.log(res.url)
            // 根路径 加 请求回来的 url 地址 就是 我们发送到服务器上那张头像的地址
            // 这里给 img.src 更改地址实现更换头像
            img.src = `http://www.liulongbin.top:3006${res.url}`
        })  
    })
  script>
body>

html>

3. 请求体类型 Content-Type

Ajax基础入门(day2) - form表单 & 文件上传_第31张图片
Ajax基础入门(day2) - form表单 & 文件上传_第32张图片
Ajax基础入门(day2) - form表单 & 文件上传_第33张图片
Ajax基础入门(day2) - form表单 & 文件上传_第34张图片
Ajax基础入门(day2) - form表单 & 文件上传_第35张图片
Ajax基础入门(day2) - form表单 & 文件上传_第36张图片
Ajax基础入门(day2) - form表单 & 文件上传_第37张图片


三、案例 - 图书管理

Ajax基础入门(day2) - form表单 & 文件上传_第38张图片

1. 请求并渲染图书列表的数据

有一个事情需要强调一下,我们写 Ajax 代码不是前端说了算,是后端说了算,看他们给的接口文档。
Ajax基础入门(day2) - form表单 & 文件上传_第39张图片

<!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"> -->
  <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. 渲染数据
    // 2. 添加数据
    // 3. 删除数据

    let tbody = document.querySelector('tbody')
    let addForm = document.querySelector('#addForm')

    // 1. 渲染数据
    axios({
            method: 'get',
            url: 'http://www.liulongbin.top:3006/api/getbooks',
           
        }).then(({data: res}) => {
            console.log(res)
            console.log(res.data)
		// 为什么是 status? 看接口文档,接口文档要求了这个属性
            if(res.status !== 200){
                alert(res.msg)
            } else {
                // 1. 渲染数据
                tbody.innerHTML = res.data.map(item =>
                    `
                    
                        ${item.id}
                            ${item.bookname}
                            ${item.author}
                            ${item.publisher}
                            
                            
                            
                        
                `
                ).join('')
            }
 
        })
  </script>
</body>

</html>

2. 添加图书

Ajax基础入门(day2) - form表单 & 文件上传_第40张图片
Ajax基础入门(day2) - form表单 & 文件上传_第41张图片
这里有一个细节,当我们点击提交按钮,成功添加图书之后,应该要把表单里的内容清空,方便我们后续的添加操作。传统做法是先获取输入框对象,然后给它的value值设置为空。但是我们这个表单有三个输入框,一个一个进行设置空操作非常麻烦。
我们有一个更简洁的做法:reset() 方法
Ajax基础入门(day2) - form表单 & 文件上传_第42张图片

<!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"> -->
  <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. 渲染数据
    // 2. 添加数据
    // 3. 删除数据

    let tbody = document.querySelector('tbody')
    let addForm = document.querySelector('#addForm')

    // 功能1. 渲染数据
   // 对代码进行封装
   function render() {
        axios({
                method: 'get',
                url: 'http://www.liulongbin.top:3006/api/getbooks',
              
            }).then(({data: res}) => {
                console.log(res)
                console.log(res.data)

                if(res.status !== 200){
                    alert(res.msg)
                } else {
                    // 1. 渲染数据
                    tbody.innerHTML = res.data.map(item =>
                        `
                        
                            ${item.id}
                                ${item.bookname}
                                ${item.author}
                                ${item.publisher}
                                
                                
                                
                            
                    `
                    ).join('')
                }
    
            })
   }
   render()
    
    // 功能2. 添加数据
    // 步骤
    // 1. 监听form的submit事件
    // 2. 阻止其默认行为
    // 3. 表单数据收集到 ==> serialize()
    // 4. axios 发送请求
    addForm.addEventListener('submit',function(e){
        // 阻止默认的提交
        e.preventDefault()

        // let data = serialize(this, {hash: true})  // 写明 hash: true 的话得到的就是 js对象
        let data = serialize(this)  // 不写明 hash: true 的话得到的就是 键值对

        console.log(data)

        axios({
            url: 'http://www.liulongbin.top:3006/api/addbook',
            method: 'post',
            data
        }).then(({data: res}) => {
            console.log(res)
            // status 主要会出现 502这个情况(重复添加信息),提示 不允许重复添加。
            // 确定 201 这个响应码 是输出 console.log(res) 在 res 中看到的
            if(res.status !== 201) {
              // 添加失败了
              alert(res.msg)
            } else {
              // 添加成功了
              // 1.重新渲染所有图书展示到 tbody 中
              render()
              // 2.清空输入栏内的内容(清空表单)
              addForm.reset()  // 用 reset() 方法重置表单

            }
        })
        
    })
  </script>
</body>

</html>

3. 删除图书

Ajax基础入门(day2) - form表单 & 文件上传_第43张图片Ajax基础入门(day2) - form表单 & 文件上传_第44张图片
Ajax基础入门(day2) - form表单 & 文件上传_第45张图片
Ajax基础入门(day2) - form表单 & 文件上传_第46张图片Ajax基础入门(day2) - form表单 & 文件上传_第47张图片
Ajax基础入门(day2) - form表单 & 文件上传_第48张图片

自定义属性 data-id 来帮助我们 实现删除功能
标签上使用 data- 自定义属性
js 中使用 dataset 属性操作

<!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"> -->
  <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. 渲染数据
    // 2. 添加数据
    // 3. 删除数据

    let tbody = document.querySelector('tbody')
    let addForm = document.querySelector('#addForm')

    // 功能1. 渲染数据
   // 对代码进行封装
   function render() {
        axios({
                method: 'get',
                url: 'http://www.liulongbin.top:3006/api/getbooks',
              
            }).then(({data: res}) => {
                console.log(res)
                console.log(res.data)

                if(res.status !== 200){
                    alert(res.msg)
                } else {
                    // 1. 渲染数据
                    tbody.innerHTML = res.data.map(item =>
                        `
                        
                            ${item.id}
                                ${item.bookname}
                                ${item.author}
                                ${item.publisher}
                                
                                
                                
                            
                    `
                    ).join('')
                }
    
            })
   }
   render()
    
    // 功能2. 添加数据
    // 步骤
    // 1. 监听form的submit事件
    // 2. 阻止其默认行为
    // 3. 表单数据收集到 ==> serialize()
    // 4. axios 发送请求
    addForm.addEventListener('submit',function(e){
        // 阻止默认的提交
        e.preventDefault()

        // let data = serialize(this, {hash: true})  // 写明 hash: true 的话得到的就是 js对象
        let data = serialize(this)  // 不写明 hash: true 的话得到的就是 键值对

        console.log(data)

        axios({
            url: 'http://www.liulongbin.top:3006/api/addbook',
            method: 'post',
            data
        }).then(({data: res}) => {
            console.log(res)
            // status 主要会出现 502这个情况(重复添加信息),提示 不允许重复添加。
            // 确定 201 这个响应码 是输出 console.log(res) 在 res 中看到的
            if(res.status !== 201) {
              // 添加失败了
              alert(res.msg)
            } else {
              // 添加成功了
              // 1.重新渲染所有图书展示到 tbody 中
              render()
              // 2.清空输入栏内的内容(清空表单)
              addForm.reset()  // 用 reset() 方法重置表单

            }
        })
        
    })

    // 功能3:删除图书
    // 给删除按钮注册click ==> 采取事件委托做法(删除按钮动态创建)
    // 做法: 把事件委托给父元素或祖先元素
    // 原理:事件冒泡
    tbody.addEventListener('click', function(e){
        console.log(e.target)

        // 判断点击的对象 是否为 删除按钮
        // if(e.target.tagName === 'BUTTON'){}

        // 更加具体些,因为我们可能不止有删除按钮,可能还有修改编辑按钮。
        if(e.target.classList.contains('btn-del')){  // contains('btn-del') 判断是否有这个类名
            // if成立,说明有 btn-del 这个类名,点击的是删除按钮

            // 点击删除按钮的时候,需要将自定义属性的值取出来
            let id = e.target.dataset.id
            console.log(id)

            // 发送 ajax 请求,告诉服务器,需要删除哪一本书
            axios({
                method: 'delete',
                url: 'http://www.liulongbin.top:3006/api/delbook',
                params: {
                    // 需要删除的图书id ==> 在删除按钮上使用自定义属性存图书的id
                    id
                }
            }).then(({data: { status, msg }}) => {
                // console.log(res)
                if(status !== 200) {
                    // 删除失败
                    alert(msg)
                } else {
                    // 删除成功 重新渲染才能看到图书被删除的效果
                    render()
                }
            })
        }
    })

  </script>
</body>

</html>

学会如何查明 bug

当删除图书时遇到一个不清楚的报错,这样解决(学会在报文中发现问题)

忘记携带参数了

Ajax基础入门(day2) - form表单 & 文件上传_第49张图片
Ajax基础入门(day2) - form表单 & 文件上传_第50张图片
Ajax基础入门(day2) - form表单 & 文件上传_第51张图片
说明我们没有提交 id

忘记用自定义属性存 id

相当于点击删除按钮的时候直接取 id,但是我们根本没在按钮上自定义 id 属性,所以无法获取。
Ajax基础入门(day2) - form表单 & 文件上传_第52张图片

Ajax基础入门(day2) - form表单 & 文件上传_第53张图片
最后点击删除按钮的时候会报错:undefined


四、axios 请求方法的别名

1. 什么是请求方法的别名

Ajax基础入门(day2) - form表单 & 文件上传_第54张图片

Ajax基础入门(day2) - form表单 & 文件上传_第55张图片

Ajax基础入门(day2) - form表单 & 文件上传_第56张图片
这样写有点麻烦,我们可以使用更简洁的写法。

2. 体验 axios.get() 的用法

Ajax基础入门(day2) - form表单 & 文件上传_第57张图片

发送 get 请求,不带参数:
Ajax基础入门(day2) - form表单 & 文件上传_第58张图片
Ajax基础入门(day2) - form表单 & 文件上传_第59张图片
发送 get 请求,带参数:
Ajax基础入门(day2) - form表单 & 文件上传_第60张图片
Ajax基础入门(day2) - form表单 & 文件上传_第61张图片
知识点补充:
从用法来说
axios.delete() 同 axios.get()
axios.put() 和 axios.patch() 同 axios.post()
Ajax基础入门(day2) - form表单 & 文件上传_第62张图片

3. 体验 axios.post() 的用法

Ajax基础入门(day2) - form表单 & 文件上传_第63张图片

发送 post 请求,不带参数:
Ajax基础入门(day2) - form表单 & 文件上传_第64张图片
Ajax基础入门(day2) - form表单 & 文件上传_第65张图片
发送 post 请求,带参数:
Ajax基础入门(day2) - form表单 & 文件上传_第66张图片
Ajax基础入门(day2) - form表单 & 文件上传_第67张图片
我们这个参数a 参数b 的值给的很随意,为什么呢?因为接口文档中明确表明: 我们设置的参数是自定义,按需提供的。
Ajax基础入门(day2) - form表单 & 文件上传_第68张图片

一个知识点:

Ajax基础入门(day2) - form表单 & 文件上传_第69张图片
timeout 的意义在于,当用户的网速太慢,网页请求时间超过我们设置的超时时间就报错停止,不要让用户傻傻等待。

4. 全局配置请求根路径

Ajax基础入门(day2) - form表单 & 文件上传_第70张图片

Ajax基础入门(day2) - form表单 & 文件上传_第71张图片

简化改写:图书管理案例

学习玩 axios 的请求别名和 全局配置请求根路径后,我们可以对之前做的图书案例的代码进行简化。

注意:
Ajax基础入门(day2) - form表单 & 文件上传_第72张图片
代码的改写:
Ajax基础入门(day2) - form表单 & 文件上传_第73张图片
Ajax基础入门(day2) - form表单 & 文件上传_第74张图片
Ajax基础入门(day2) - form表单 & 文件上传_第75张图片


五、总结

Ajax基础入门(day2) - form表单 & 文件上传_第76张图片

你可能感兴趣的:(Ajax入门到精通,ajax,前端,javascript)