AJAX初级

AJAX的概念:

  • 使用浏览器的 XMLHttpRequest 对象 与服务器通信

  • 浏览器网页中,使用 AJAX技术(XHR对象)发起获取省份列表数据的请求,服务器代码响应准备好的省份列表数据给前端,前端拿到数据数组以后,展示到网页

服务器可以展示理解为提供数据的一台电脑,学了AJAX,我们的数据就可以在服务器上获取,让数据变活。

怎么学 AJAX ?

  • 这里使用一个第三方库叫 axios, 后续在学习 XMLHttpRequest 对象了解 AJAX 底层原理

  • 因为 axios 库语法简单,让我们有更多精力关注在与服务器通信上,而且后续 Vue,React 学习中,也使用 axios 库与服务器通信

需求:从服务器获取省份列表数据,展示到页面上(体验 axios 语法的使用)

获取省份列表数据 - 目标资源地址:http://hmajax.itheima.net/api/province

axios 语法

引入 axios.js 文件到自己的网页中

axios.js文件链接: https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js

明确axios函数的使用语法

 
axios({
   url: '目标资源地址'
 }).then((result) => {
   // 对服务器返回的数据做后续处理
 })

注意:请求的 url 地址, 就是标记资源的网址

<!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>AJAX概念和axios使用</title>
</head>

<body>
  <!--
    axios库地址:https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js
    省份数据地址:http://hmajax.itheima.net/api/province

    目标: 使用axios库, 获取省份列表数据, 展示到页面上
    1. 引入axios库
  -->
  <p class="my-p"></p>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    // 2. 使用axios函数
    axios({
      url: 'http://hmajax.itheima.net/api/province'
    }).then(result => {
      console.log(result)
      // 好习惯:多打印,确认属性名
      console.log(result.data.list)
      console.log(result.data.list.join('<br>'))
      // 把准备好省份列表,插入到页面
      document.querySelector('.my-p').innerHTML = result.data.list.join('<br>') 
    })
  </script>
</body>

</html>

URL

URL的概念:

统一资源定位符,简称网址,用于定位网络中的资源(资源指的是:网页,图片,数据,视频,音频等等)

URL的组成:

协议,域名,资源路径

http 协议:叫超文本传输协议,规定了浏览器和服务器传递数据的格式

域名:标记服务器在互联网当中的方位,网络中有很多服务器,你想访问哪一台,就需要知道它的域名才可以

资源路径:一个服务器内有多个资源,用于标识你要访问的资源具体的位置接下来做个需求,访问新闻列表的 URL 网址,打印新闻数据

新闻列表数据 URL 网址:http://hmajax.itheima.net/api/news

axios({
  url: 'http://hmajax.itheima.net/api/news'
}).then(result => {
  console.log(result)
})

url解释:从黑马服务器使用http协议,访问/api/news路径下的新闻列表资源

URL 查询参数

查询参数 :

  • 携带给服务器额外信息,让服务器返回我想要的某一部分数据而不是全部数据

  • 举例:查询河北省下属的城市列表,需要先把河北省传递给服务器

查询参数的语法:

  • 在 url 网址后面用?拼接格式:XXXX?参数名1=值1&参数名2=值

  • 参数名一般是后端规定的,值前端看情况传递即可

axios 如何携带查询参数:

使用 params 选项即可

axios({
  url: '目标资源地址',
  params: {
    参数名: 值
  }
}).then(result => {
  // 对服务器返回的数据做后续处理
})

查询城市列表的 url地址:http://hmajax.itheima.net/api/city

参数名:pname (值要携带省份名字)

获取“河北省”下属的城市列表,展示到页面,对应代码:
<!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>
</head>
<body>
  <!-- 
    城市列表: http://hmajax.itheima.net/api/city
    参数名: pname
    值: 省份名字
  -->
  <p></p>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    axios({
      url: 'http://hmajax.itheima.net/api/city',
      // 查询参数
      params: {
        pname: '辽宁省'
      }
    }).then(result => {
      console.log(result.data.list)
      document.querySelector('p').innerHTML = result.data.list.join('<br>')
    })
  </script>
</body>
</html>

案例-查询-地区列表

  1. 需求:根据输入的省份名字和城市名字,查询下属地区列表相关参数

查询地区: http://hmajax.itheima.net/api/area

参数名:

pname:省份名字

cname:城市名字

/*
      获取地区列表: http://hmajax.itheima.net/api/area
      查询参数:
        pname: 省份或直辖市名字
        cname: 城市名字
    */
// 目标: 根据省份和城市名字, 查询地区列表
// 1. 查询按钮-点击事件
document.querySelector('.sel-btn').addEventListener('click', () => {
    // 2. 获取省份和城市名字
    let pname = document.querySelector('.province').value
    let cname = document.querySelector('.city').value

    // 3. 基于axios请求地区列表数据
    axios({
        url: 'http://hmajax.itheima.net/api/area',
        params: {
            pname,
            cname
        }
    }).then(result => {
        // console.log(result)
        // 4. 把数据转li标签插入到页面上
        let list = result.data.list
        console.log(list)
        let theLi = list.map(areaName => `<li class="list-group-item">${areaName}</li>`).join('')
        console.log(theLi)
        document.querySelector('.list-group').innerHTML = theLi
    })
})

常用请求方法和数据提交

想要提交数据,先来了解什么是请求方法:

  • 请求方法是一些固定单词的英文,例如:GET,POST,PUT,DELETE,PATCH(这些都是http协议规定的),每个单词对应一种对服务器资源要执行的

  1. GET:获取数据

  2. POST:数据提交

  3. PUT:修改数据(全部)

  4. DELETE:删除数据

  5. PATCH:修改数据(部分)

  • 前面我们获取数据其实用的就是GET请求方法,但是axios内部设置了默认请求方法就是GET,我们就没有写

  • 但是提交数据需要使用POST请求方法

什么时候进行数据提交:

例如:多端要查看同一份订单数据,或者使用同一个账号进行登录,那订单/用户名+密码,就需要保存在服务器上,随时随地进行访问

axios 如何提交数据到服务器:

需要学习,method 和 data 这2个新的选项了(大家不用担心,这2个学完,axios常用的选项就都学完了)

axios({
  url: '目标资源地址',
  method: '请求方法',
  data: {
    参数名: 值
  }
}).then(result => {
  // 对服务器返回的数据做后续处理
})

需求:注册账号,提交用户名和密码到服务器保存:

注册用户 URL 网址:http://hmajax.itheima.net/api/register

请求方法:POST

参数名:

username:用户名(要求中英文和数字组成,最少8位)

password:密码(最少6位)

/*
  注册用户:http://hmajax.itheima.net/api/register
  请求方法:POST
  参数名:
    username:用户名(中英文和数字组成,最少8位)
    password:密码  (最少6位)

  目标:点击按钮,通过axios提交用户和密码,完成注册
*/
document.querySelector('.btn').addEventListener('click', () => {
  axios({
    url: 'http://hmajax.itheima.net/api/register',
    method: 'POST',
    data: {
      username: 'itheima007',
      password: '7654321'
    }
  })
})

请求方法最常用的是:

POST 提交数据,GET 查询数据

axios 的核心配置项:

url:目标资源地址,method:请求方法,params:查询参数,data:提交的数据

axios 错误处理

如果注册相同的用户名,则会遇到注册失败的请求,也就是 axios 请求响应失败了,你会在控制台看到如图的错误:

  1. 在 axios 语法中要如何处理呢?

    • 因为,普通用户不会去控制台里看错误信息,我们要编写代码拿到错误并展示给用户在页面上

  2. 使用 axios 的 catch 方法,捕获这次请求响应的错误并做后续处理,语法如下:

     axios({
       // ...请求选项
     }).then(result => {
       // 处理成功数据
     }).catch(error => {
       // 处理失败错误
     })
  3. 需求:再次重复注册相同用户名,提示用户注册失败的原因

    document.querySelector('.btn').addEventListener('click', () => {
        axios({
          url: 'http://hmajax.itheima.net/api/register',
          method: 'post',
          data: {
            username: 'itheima007',
            password: '7654321'
          }
        }).then(result => {
          // 成功
          console.log(result)
        }).catch(error => {
          // 失败
          // 处理错误信息
          console.log(error)
          console.log(error.response.data.message)
          alert(error.response.data.message)
        })
    })

    HTTP 协议-请求报文

 HTTP 协议规定了浏览器和服务器返回内容的格式

请求报文:是浏览器按照协议规定发送给服务器的内容,例如刚刚注册用户时,发起的请求报文:

  1. 这里的格式包含:

  • 请求行:请求方法,URL,协议
  • 请求头:以键值对的格式携带的附加信息,比如:Content-Type(指定了本次传递的内容类型)
  • 空行:分割请求头,空行之后的是发送给服务器的资源
  • 请求体:发送的资源
  1. 我们切换到浏览器中,来看看刚才注册用户发送的这个请求报文以及内容去哪里查看呢

  2. 代码:直接在上个代码基础上复制,然后运行查看请求报文对应关系即可

  1. 浏览器发送给服务器的内容叫做,请求报文

  2. 请求报文的组成是什么?

    ​请求行,请求头,空行,请求体
  3. 通过 Chrome 的网络面板如何查看请求体?

请求报文-错误排查

学习了查看请求报文可以用来确认我们代码发送的请求数据是否真的正确

HTTP 协议-响应报文

响应报文:是服务器按照协议固定的格式,返回给浏览器的内容

  1. 响应报文的组成:

  • 响应行(状态行):协议,HTTP响应状态码,状态信息
  • 响应头:以键值对的格式携带的附加信息,比如:Content-Type(告诉浏览器,本次返回的内容类型)
  • 空行:分割响应头,控制之后的是服务器返回的资源
  • 响应体:返回的资源

HTTP 响应状态码:

  • 用来表明请求是否成功完成

  • 例如:404(客户端要找的资源,在服务器上不存在)

接口文档

  1. 接口文档:描述接口的文章(一般是后端工程师,编写和提供)

  2. 接口:指的使用 AJAX 和 服务器通讯时,使用的 URL,请求方法,以及参数,例如:AJAX阶段接口文档

  3. 例如:获取城市列表接口样子

需求:打开 AJAX 阶段接口文档,查看登录接口,并编写代码,完成一次登录的效果

document.querySelector('.btn').addEventListener('click', () => {
  // 用户登录
  axios({
    url: 'http://hmajax.itheima.net/api/login',
    method: 'post',
    data: {
      username: 'itheima007',
      password: '7654321'
    }
  })
})

案例-用户登录-主要业务

  1. 需求:编写代码,查看接口文档,填写相关信息,完成登录业务

  2. 分析实现的步骤

  • 点击登录,获取并判断用户名和长度

  • 提交数据和服务器通信

  • 提示信息,反馈给用户

// 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信

// 1.1 登录-点击事件
document.querySelector('.btn-login').addEventListener('click', () => {
  // 1.2 获取用户名和密码
  const username = document.querySelector('.username').value
  const password = document.querySelector('.password').value
  // console.log(username, password)

  // 1.3 判断长度
  if (username.length < 8) {
    console.log('用户名必须大于等于8位')
    return // 阻止代码继续执行
  }
  if (password.length < 6) {
    console.log('密码必须大于等于6位')
    return // 阻止代码继续执行
  }

  // 1.4 基于axios提交用户名和密码
  // console.log('提交数据到服务器')
  axios({
    url: 'http://hmajax.itheima.net/api/login',
    method: 'POST',
    data: {
      username,
      password
    }
  }).then(result => {
    console.log(result)
    console.log(result.data.message)
  }).catch(error => {
    console.log(error)
    console.log(error.response.data.message)
  })
})

总结下用户登录案例的思路:

1. 登录按钮-绑定点击事件 2. 从页面输入框里,获取用户名和密码 3. 判断长度是否符合要求 4. 基于 axios 提交用户名和密码

案例-用户登录-提示信息

需求:使用提前准备好的提示框,来把登录成功/失败结果提示给用户

  1. 使用提示框,反馈提示消息,因为有4处地方需要提示框,所以封装成函数

    1. 获取提示框

    2. 封装提示框函数,重复调用,满足提示需求

      功能:

      1. 显示提示框

      2. 不同提示文字msg,和成功绿色失败红色isSuccess参数(true成功,false失败)

      3. 过2秒后,让提示框自动消失

对应提示框核心代码:

/**
 * 2.2 封装提示框函数,重复调用,满足提示需求
 * 功能:
 * 1. 显示提示框
 * 2. 不同提示文字msg,和成功绿色失败红色isSuccess(true成功,false失败)
 * 3. 过2秒后,让提示框自动消失
*/
function alertFn(msg, isSuccess) {
  // 1> 显示提示框
  myAlert.classList.add('show')

  // 2> 实现细节
  myAlert.innerText = msg
  const bgStyle = isSuccess ? 'alert-success' : 'alert-danger'
  myAlert.classList.add(bgStyle)

  // 3> 过2秒隐藏
  setTimeout(() => {
    myAlert.classList.remove('show')
    // 提示:避免类名冲突,重置背景色
    myAlert.classList.remove(bgStyle)
  }, 2000)
}

form-serialize 插件

使用 form-serialize 插件,快速收集目标表单范围内表单元素的值

  1. 我们前面收集表单元素的值,是一个个标签获取的

  2. 如果一套表单里有很多很多表单元素,如何一次性快速收集出来呢?

  3. 使用 form-serialize 插件提供的 serialize 函数就可以办到

  4. form-serialize 插件语法:

    1. 引入 form-serialize 插件到自己网页中

    2. 使用 serialize 函数

      • 参数1:要获取的 form 表单标签对象(要求表单元素需要有 name 属性-用来作为收集的数据中属性名)

      • 参数2:配置对象

        • hash:

          • true - 收集出来的是一个 JS 对象结构

          • false - 收集出来的是一个查询字符串格式

        • empty:

          • true - 收集空值

          • false - 不收集空值

  5. 需求:收集登录表单里用户名和密码

<!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>form-serialize插件使用</title>
</head>

<body>
  <form action="javascript:;" class="example-form">
    <input type="text" name="username">
    <br>
    <input type="text" name="password">
    <br>
    <input type="button" class="btn" value="提交">
  </form>
  <!-- 
    目标:在点击提交时,使用form-serialize插件,快速收集表单元素值
    1. 把插件引入到自己网页中
  -->
  <script src="./lib/form-serialize.js"></script>
  <script>
    document.querySelector('.btn').addEventListener('click', () => {
      /**
       * 2. 使用serialize函数,快速收集表单元素的值
       * 参数1:要获取哪个表单的数据
       *  表单元素设置name属性,值会作为对象的属性名
       *  建议name属性的值,最好和接口文档参数名一致
       * 参数2:配置对象
       *  hash 设置获取数据结构
       *    - true:JS对象(推荐)一般请求体里提交给服务器
       *    - false: 查询字符串
       *  empty 设置是否获取空值
       *    - true: 获取空值(推荐)数据结构和标签结构一致
       *    - false:不获取空值
      */
      const form = document.querySelector('.example-form')
      const data = serialize(form, { hash: true, empty: true })
      // const data = serialize(form, { hash: false, empty: true })
      // const data = serialize(form, { hash: true, empty: false })
      console.log(data)
    })
  </script>
</body>

</html>

用户登录-form-serialize

  1. 基于模板代码,使用 form-serialize 插件来收集用户名和密码

  2. 在原来的代码基础上修改即可

    1. 先引入插件

       <!-- 3.1 引入插件 -->
       <script src="./lib/form-serialize.js"></script>

案例_图书管理-介绍

介绍要完成的增删改查业务效果和 Bootstrap 弹框使用

分析步骤和对应的视频模块

  • 先学习 Bootstrap 弹框的使用(因为添加图书和编辑图书需要这个窗口来承载图书表单)

  • 先做渲染图书列表(这样做添加和编辑以及删除可以看到数据变化,所以先做渲染)

  • 再做新增图书功能

  • 再做删除图书功能

  • 再做编辑图书功能(注意:编辑和新增图书是2套弹框-后续做项目我们再用同1个弹框)

Bootstrap 弹框_属性控制

使用属性方式控制 Bootstarp 弹框的显示和隐藏

什么是 Bootstrap 弹框?

  • 不离开当前页面,显示单独内容,供用户操作

需求:使用 Bootstrap 弹框,先做个简单效果,点击按钮,让弹框出现,点击 X 和 Close 让弹框隐藏

如何使用 Bootstrap 弹框呢?

  1. 先引入 bootstrap.css 和 bootstrap.js 到自己网页中

  2. 准备弹框标签,确认结构(可以从 Bootstrap 官方文档的 Modal 里复制基础例子)- 运行到网页后,逐一对应标签和弹框每个部分对应关系

  3. 通过自定义属性,通知弹框的显示和隐藏,语法如下:

<button data-bs-toggle="modal" data-bs-target="css选择器">
  显示弹框
</button>

<button data-bs-dismiss="modal">Close</button>
<!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>Bootstrap 弹框</title>
  <!-- 引入bootstrap.css -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>
  <!-- 
    目标:使用Bootstrap弹框
    1. 引入bootstrap.css 和 bootstrap.js
    2. 准备弹框标签,确认结构
    3. 通过自定义属性,控制弹框的显示和隐藏
   -->
  <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target=".my-box">
    显示弹框
  </button>

  <!-- 
    弹框标签
    bootstrap的modal弹框,添加modal类名(默认隐藏)
   -->
  <div class="modal my-box" tabindex="-1">
    <div class="modal-dialog">
      <!-- 弹框-内容 -->
      <div class="modal-content">
        <!-- 弹框-头部 -->
        <div class="modal-header">
          <h5 class="modal-title">Modal title</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <!-- 弹框-身体 -->
        <div class="modal-body">
          <p>Modal body text goes here.</p>
        </div>
        <!-- 弹框-底部 -->
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          <button type="button" class="btn btn-primary">Save changes</button>
        </div>
      </div>
    </div>
  </div>

  <!-- 引入bootstrap.js -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script>
</body>

</html>

Bootstrap 弹框_JS控制

使用 JS 方式控制 Bootstarp 弹框的显示和隐藏

为什么需要 JS 方式控制呢?

  • 当我显示之前,隐藏之前,需要执行一些 JS 逻辑代码,就需要引入 JS 控制弹框显示/隐藏的方式了

  • 例如:

    • 点击编辑姓名按钮,在弹框显示之前,在输入框填入默认姓名

    • 点击保存按钮,在弹框隐藏之前,获取用户填入的名字并打印

// 1. 创建弹框对象
const modalDom = document.querySelector('.name-box')
const modal = new bootstrap.Modal(modalDom)

// 编辑姓名->点击->赋予默认姓名->弹框显示
document.querySelector('.edit-btn').addEventListener('click', () => {
  document.querySelector('.username').value = '默认姓名'

  // 2. 显示弹框
  modal.show()
})

// 保存->点击->->获取姓名打印->弹框隐藏
document.querySelector('.save-btn').addEventListener('click', () => {
  const username = document.querySelector('.username').value
  console.log('模拟把姓名保存到服务器上', username)

  // 2. 隐藏弹框
  modal.hide()
})

直接出现/隐藏用属性方式控制,如果需要先执行一段 JS 逻辑再显示/隐藏就用 JS 方式控制

案例_图书管理_渲染列表

基于 axios 获取到图书列表数据,并用 JS 代码渲染数据,到准备好的模板标签中

步骤:

  1. 获取数据

  2. 渲染数据

我们所有人数据都来自同一个服务器上,为了区分每个同学不同的数据,需要大家设置一个外号告诉服务器,服务器就会返回你对应的图书数据了

因为默认展示列表,新增,修改,删除后都要重新获取并刷新列表,所以把获取数据渲染数据的代码封装在一个函数内,方便复用

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

案例_图书管理_新增图书

点击添加按钮,出现准备好的新增图书弹框,填写图书信息提交到服务器保存,并更新图书列表

步骤:

  1. 新增弹框(控制显示和隐藏)(基于 Bootstrap 弹框和准备好的表单-用属性和 JS 方式控制)

  2. 在点击保存按钮时,收集数据&提交保存

  3. 刷新-图书列表(重新调用下之前封装的获取并渲染列表的函数)

/**
 * 目标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()
  })
})

案例_图书管理_删除图书

点击图书删除元素,删除当前图书数据

步骤:

  1. 给删除元素,绑定点击事件(事件委托方式并判断点击的是删除元素才走删除逻辑代码),并获取到要删除的数据id

  2. 基于 axios 和接口文档,调用删除接口,让服务器删除这条数据

  3. 重新获取并刷新图书列表

/**
 * 目标3:删除图书
 *  3.1 删除元素绑定点击事件->获取图书id
 *  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()
    })
  }
})

案例_图书管理_编辑图书

完成编辑图书回显当前图书数据到编辑表单,在用户点击修改按钮,收集数据提交到服务器保存,并刷新列表

  1. 编辑数据的核心思路:

    1. 给编辑元素,绑定点击事件(事件委托方式并判断点击的是编辑元素才走编辑逻辑代码),并获取到要编辑的数据id

    2. 基于 axios 和接口文档,调用查询图书详情接口,获取正在编辑的图书数据,并回显到表单中(页面上的数据是在用户的浏览器中不够准备,所以只要是查看数据都要从服务器获取)

    3. 收集并提交保存修改数据,并重新从服务器获取列表刷新页面

/**
 * 目标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
    axios({
      url: `http://hmajax.itheima.net/api/books/${theId}`
    }).then(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']
      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})
  // 保存正在编辑的图书id,隐藏起来:无需让用户修改
  // <input type="hidden" class="id" name="id" value="84783">
  axios({
    url: `http://hmajax.itheima.net/api/books/${id}`,
    method: 'PUT',
    data: {
      bookname,
      author,
      publisher,
      creator
    }
  }).then(() => {
    // 修改成功以后,重新获取并刷新列表
    getBooksList()

    // 隐藏弹框
    editModal.hide()
  })
})

案例_图书管理_总结

因为增删改查的业务在前端实际开发中非常常见,思路是可以通用的,所以总结下思路

1.渲染列表(查)

2.新增图书(增)

3.删除图书(删)

4.编辑图书(改)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值