Ajax笔记(上)

知识点自测

1.哪个赋值会让浏览器解析成标签显示

(1)inner.Text = str

(2)inner.HTML = str

选择(2),因为innerText会将字符串当做普通字符串,innerHTML会试着将字符串解析成标签,如果是普通的字符串,则显示普通文本字符串

2.哪个是获取输入框的值

(1).innnerHTML

(2).value

选择(2),因为表单标签设置或获取值使用value,其他标签使用innerHTML/innerText

进行获取和设置

一、Ajax概念和axios库的使用

1.什么是AJax?mdn

*使用浏览器的XML HttpRequest对象与服务器之间的通信,

*浏览器网页中,使用AJax技术(XHR)发送获取省份列表数据的请求

,服务器代码响应准备的省份列表数据给前端,前端拿到数据后,展示到网页

2.什么是服务器?

可以暂时理解为提供数据的一台电脑

3.为什么学习Ajax?

*以前数据都是写在代码中固定的,无法随时改变

*现在可以让我们的数据从服务器上进行获取,让数据变火

4、如何学?

*使用axios第三方库,后续在学习中XML HttpRequest对象了解AJax底层原理

*因为axios语法简单,让我们可以有更多精力放在服务器通信上,而且Vue和React也会使用

5.语法?

axios ({

url:'目标的地址'

}).then((result)=>{

//对服务器返回的数据做后续处理

}

总结:

(1)Ajax有什么用?

浏览器和服务器之间进行通信,动态数据交互

(2)如何学?

先学会使用axios库,再了解XML HttpRequest原理

二、认识URL

1.为什么要认识URL,mdn?

*虽然是后端给我的一个地址,但是哪部分标记的是服务器电脑,那部分标记的是资源?

可以和服务器进行有效的沟通

2.什么是URL?

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

3.组成?

协议+域名+资源路径

4.什么是http协议?

超文本传输协议,规定了浏览器传递数据的格式

5.什么是域名?

标记服务器在互联网当中的定位,网络中有很多服务器,想访问那一台,就需要知道他的域名

6.什么是资源路径?

一个服务器中有很多资源,用于标识你要访问的资源具体位置

总结:

(1)URL是什么?

统一资源定位符,网址,用于访问服务器上资源

(2)解释URL,并且分析每个部分的作用

协议://域名/资源路径

三、URL查询参数

1.什么是查询参数?

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

2.查询参数的语法:

拼接格式为:http://xxxx.com/xxxx/xxx?参数名1=值1\&参数名2=值2

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

3.axios如何携带查询参数?

使用params选项即可

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

4.需求:获取某个省份的城市列表,并将其展示到页面上

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>
</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)URL查询参数有什么用?

浏览器提供给服务器的额外信息,获取对应的数据

(2)axios该如何携带查询参数?

使用params选项,携带参数名和值在对象结构中

四、常用请求方法和数据提交

1、请求方法?

是一些固定单词的英文,例如:GET,POST,PUT,DELETE,PATCH,(这些都是HTTP协议规定的),每个单词都对应一种对服务器要执行的操作

2.axios如何提交数据到服务器?

需要学习method和data这两个选项,

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

总结:

(1)请求数据的最常用的两个方法,分别有什么作用?

POST提交数据;GET查询数据

(2)axios的核心配置项?

url:目标资源地址,method:请求方法,

params:查询参数,data:提交数据

五、axios错误处理

1.如果注册相同的用户名,则会遇到注册失败的请求,也就是axios请求axios请求响应失败,将会看到

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

因为,普通用户不会看错误信息,需要将错误展示到页面

3.使用axios的catch方法,捕获这次请求响应的错误

javascript 复制代码
axios({
  // ...请求选项
}).then(result => {
  // 处理成功数据
}).catch(error => {
  // 处理失败错误
})

4.需求:再次重复注册相同用户名,提示用户注册失败的原因

5、对应代码:

javascript 复制代码
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)
    })
})

总结:

通过axios函数调用后,在后面接着调用.catch方法捕获

六、HTTP协议-请求报文

1.http协议首先规定了浏览器和服务器返回的内容格式

2.请求报文:

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

3.请求格式:

  • 请求行:请求方法,URL,协议

  • 请求头:以键值对的格式携带的附加信息,比如:Content-Type(指定了本次传递的内容类型)

空行:分割请求头,空行之后的是发送给服务器的资源

  • 请求体:发送的资源

总结:

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

(2)组成:

请求行,请求头,空行,请求体

(3)通过Chrome的网络面板查看请求体:

七、请求报文-错误排查

学习了查看请求报文有什么用呢?

可以用来确认我们代码发送的请求数据是否真的正确
2.

配套模板代码里,对应 08 标题文件夹里是我同桌的代码,它把登录也写完了,但是无法登录,我们来到模板代码中,找到运行后,在<span style="color: red;">不逐行查看代码的情况下</span>,查看请求报文,看看它登录提交的相关信息对不对,帮他找找问题出现的原因

发现请求体数据有问题,往代码中定位,找到类名写错误了

代码在配套文件夹素材里,找到需要对应代码,直接运行,根据报错信息,找到错误原因

总结:

学会查看请求报文,可以对实际应用开发,可以快速的确认我们发送的内容是否正确

八、HTTP协议-响应报文

1.响应报文:

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

2.响应报文的组成:

  • 响应行(状态行):协议,HTTP响应状态码,状态信息

  • 响应头:以键值对的格式携带的附加信息,比如:Content-Type(告诉浏览器,本次返回的内容类型)

  • 空行:分割响应头,控制之后的是服务器返回的资源

  • 响应体:返回的资源

3.HTTP 响应状态码:

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

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

总结:

HTTP响应状态码是干什么的?

表明请求是否成功完成,2xx都是成功的

九、接口文档

1.接口文档:

描述接口的文章(一般都是后端编写和提供)

2.接口:

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

总结:

(1)接口文档是什么?

由后端提供的描述接口的文章

(2)接口文档包含什么?

请求的URL网址,请求方法,请求参数,说明

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

(1)分析实现的步骤

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

提交数据和服务器通信

提示信息,反馈给用户(这节课先来完成前 2 个步骤)

(2)代码:

javascript 复制代码
// 目标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.步骤:

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

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

  • 再做新增图书功能

  • 再做删除图书功能

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

2.Bootstrap弹框-属性控制

(1)什么是bootstrap弹框?

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

(2)如何使用Bootstrap?

1.先引入bootstrap.css和bootstrap.js
2准备弹框标签,确认结构
3通过自定义属性,通知弹框的显示和隐藏
html 复制代码
<button data-bs-toggle="modal" data-bs-target="css选择器">
  显示弹框
</button>

<button data-bs-dismiss="modal">Close</button>

(3)代码实现

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>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>

###通过data-bs-toggle和data-bs-target绑定属性控制弹框显示

data-ba-dismiss关闭弹框

3.Bootstrap弹框-js控制

###在显示和隐藏之前,需要通过JS代码逻辑,就使用JS方式控制Bootstrap弹框的显示和隐藏

代码实现:

javascript 复制代码
// 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方式控制

4.案例-图书管理-渲染列表

(1)步骤:

获取数据、分析结构渲染到页面上

代码实现:

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

5.案例-图书管理-新增图书

(1)步骤:

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

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

3.刷新图书列表(重新调用之前封装的获取并渲染列表的元素)

(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()
  })

6.案例-图书管理-删除图书

(1)步骤:

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

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

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

(2)核心代码

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

7.案例-图书管理-编辑图书

(1)步骤:

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

2.基于axios和接口文档,调查查询图书详情接口,获取正在编辑的图书数据,并回显到表单中

(页面上的数据是在用户的浏览器不够准备,所以只要是查看数据都要从服务器中获取)

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

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
    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()
  })
})

8.总结:

(1)增删改查的业务是前端实际开发中非常常见,思路是通用的

1.渲染页面(查)

核心思路:获取数据 -> 渲染数据

javascript 复制代码
// 1.1 获取数据
axios({...}).then(result => {
  const bookList = result.data.data
  // 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('')
  document.querySelector('.list').innerHTML = htmlStr
})

2.新增图书(增)

核心思路:准备页面标签 -> 收集数据提交(必须) -> 刷新页面列表(可选)

javascript 复制代码
// 3.1 删除元素->点击(事件委托)
document.querySelector('.list').addEventListener('click', e => {
  if (e.target.classList.contains('del')) {
    // 获取图书id(自定义属性id)
    const theId = e.target.parentNode.dataset.id
    // 3.2 调用删除接口
    axios({...}).then(() => {
      // 3.3 刷新图书列表
      getBooksList()
    })
  }
})

3.删除图书(删)

核心思路:绑定点击事件(获取要删除的图书唯一标识) -> 调用删除接口(让服务器删除此数据) -> 成功后重新获取并刷新列表

javascript 复制代码
// 3.1 删除元素->点击(事件委托)
document.querySelector('.list').addEventListener('click', e => {
  if (e.target.classList.contains('del')) {
    // 获取图书id(自定义属性id)
    const theId = e.target.parentNode.dataset.id
    // 3.2 调用删除接口
    axios({...}).then(() => {
      // 3.3 刷新图书列表
      getBooksList()
    })
  }
})

4.编辑图书(改)

核心思路:准备编辑图书表单 -> 表单回显正在编辑的数据 -> 点击修改收集数据 -> 提交到服务器保存 -> 重新获取并刷新列表

javascript 复制代码
// 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({...}).then(result => {
      const bookObj = result.data.data
      // 遍历数据对象,使用属性去获取对应的标签,快速赋值
      const keys = Object.keys(bookObj) 
      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({...}).then(() => {
    getBooksList()
    editModal.hide()
  })
})