前端AJAX与后台交互技术知识点及案例(续2)

news2024/9/20 5:36:03

以下笔记均为学习哔站黑马程序员AJAX视频所得!!!

AJAX作用:浏览器和服务器之间通信,动态数据交互

axios函数

先引入axios库,可在bootcdn中寻找相关js文件或者对应的script标签

    axios({
      url:'http://hmajax.itheima.net/api/provice'//获取数据的地址
    }).then(result=>{
      console.log(result)//一个对象
      console.log(result.data.list)//一个数组
      console.log(result.data.list.join('<br>'))//将数组中的元素以换行线隔开
      document.querySelector('p').innerHTML=result.data.list.join('<br>')
    })

 URL

  • http协议:超文本传输协议,规定浏览器和服务器之间传输数据的格式
  • 域名:标记服务器在互联网中方位(必须)
  • 资源路径:标记资源在服务器下的具体位置
        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>')
        })

URL查询参数

定义:浏览器提供给服务的额外信息,让服务器返回浏览器想要的数据

语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2

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

axios-查询参数

语法:使用axios提供的params选项

注意:axios在运行时把参数名和值,会拼接到url?参数名=值

地区查询(从服务器中获取数据)

需求:根据输入的省份名字和城市名字,查询地区并渲染列表

首先:确定URL网址和参数说明

  • 查询某个省内某个城市的所有地区:http://hmajax.itheima.net/api/area
  • 参数名:
  • pname:省份名字或直辖市名字,比如北京,福建省,辽宁省
  • cname:城市名字,比如北京市,厦门市,大连市 

完整:http://hmajax.itheima.net/api/area?pname=北京&cname=北京市

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
<style>
  :root {
    font-size: 15px;
  }
  body {
    padding-top: 15px;
  }
  .mb-3 {
    display: inline-block;
  }
  li {
    list-style: none;
  }
</style>
</head>
<body>
  <div class="container">
    <form id="ediForm" class="row">
      <div class="mb-3 col">
        <label class="form-lable">省份名字</label>
        <input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名称" >
      </div>
      <div class="mb-3 col">
        <label class="form-lable">城市名字</label>
        <input type="text" value="北京市" name="city" class="form-control city" placeholder="请输入城市名称" >
      </div>
    </form>
    <button type="button" class="btn btn-primary sel-btn">查询</button>
    <br>
    <p>地区列表:</p>
    <ul class="list-group">
      <!-- 实例地区 -->
      <li class="list-group-item">东城区</li>
    </ul>
  </div>
  <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.6.8/axios.min.js"></script>
  <script>
    document.querySelector('.sel-btn').addEventListener('click',()=>{
      // 获取省份和城市名字
      let pName=document.querySelector('.province').value
      let cName=document.querySelector('.city').value
      // 基于axios请求地区列表数据
      axios({
        url: 'http://hmajax.itheima.net/api/area',
        params:{
          pname:pName,
          cname:cName//pname和cname为后端规定接口,不可随意改变,当要传进去的参数和pname,cname同名时,可以简化,params中只写pname,cname
        }
      }).then(result=>{
        // 把数据转成li标签 插入到页面上
        let list=result.data.list
        console.log(list)
        let theLi=list.map(areaName=>`
        <li class="list-group-item">${areaName}</li>
        `).join('')
      document.querySelector('.list-group').innerHTML=theLi
      })//theLi里面包含了很多个li标签,将其转化为字符串用join
    })
  </script>
</body>
</html>

常用请求方法:

 请求方法:对服务器资源,要执行的操作

请求方法操作
GET获取数据
POST提交数据
PUT修改数据
DELETE删除数据
PATCH修改数据(部分)

数据提交

当数据需要在服务器上保存

axios请求配置

  • url:请求的URL地址
  • method:请求的方法,GET方法可以省略(不区分大小写)
  • data:提交数据

数据提交-注册账号

  • 需求:通过axios提交用户名和密码,完成注册功能
  • 注册用户URL地址: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:'zj05090429',
          password:'123456'
        }
      }).then(result=>{
        console.log(result)
      })
    })

在上述代码中,再次注册相同的账号,会遇到报错信息,提示,账号已被占用

 

 axios错误处理

场景:再次注册相同的账号,会遇到报错处理

处理:用更直观的方式,给普通用户展示错误信息,如下:

语法:在then方法的后面,通过点语法调用catch方法,传入回调函数并定义形参

 

处理:注册案例,重复注册时通过弹框提示用户错误原因

      axios({
        url:'http://hmajax.itheima.net/api/register',
        // 指定请求方法
        method:'post',
        // 提交数据
        data:{
          username:'zj05090429',
          password:'123456'
        }
      }).then(result=>{
        // 成功
        console.log(result)
      }).catch(error=>{
        // 失败
        // 处理错误信息
        // console.log(error)
        // console.log(error.response.data.message)
        alert(error.response.data.message)
      })
    })

 HTTP协议-请求报文

HTTP协议:规定了浏览器发送及服务器返回内容的格式

请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容

请求报文的组成部分有:

1.请求行:请求方法,URL,协议

2.请求头:以键值对的格式携带的附加信息,比如:Content-type

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

4.请求体:发送的资源

最终会将传入的数据对象转化为JSON字符串携带到请求报文中

请求报文-错误排查,可通过查看载荷中传入的数据进行分析排查

HTTP协议-响应报文

响应报文:服务器按照HTTP协议要求的格式,返回给浏览器的内容

1.相应行(状态行):协议、HTTP响应状态码、状态信息

2.相应头:以键值对的格式写到的附加信息,比如:Content-Type

3.空行:分隔响应头,空行之后的是服务器返回的资源

4.响应体:返回的资源

HTTP响应状态码:用来表明请求是否成功完成

比如:404(服务器找不到资源)

状态码说明
1xx信息
2xx 成功
3xx重定向消息
4xx客户端错误
5xx服务端错误

 接口文档

接口文档:描述接口的文章

接口:使用AJAX和服务器通讯时,请求方法,以及参数

    axios({
        url:'http://hmajax.itheima.net/api/login',
        method:'post',
        data:{
          username:'itheima007',
          password:'7654321'
        }
      })
    })

 案例-用户登录

1.点击登录时,判断用户名和密码长度

2.提交数据和服务器通信

3.提示信息

    const myAlert=document.querySelector('.alert')
    // 封装提示框函数,重复调用 满足提示需求
    // 功能:
    // 1.显示提示显示框
    // 2.不同提示文字msg,和成功绿色失败红色 issucess(true成功,false失败)
    // 3.过两秒之后,让提示框自动消失
      function alertFn(msg,isSucess){
        // 显示提示框
        myAlert.classList.add('show')
        // 实现细节
        myAlert.innerText=msg
        const bgStyle=isSucess?'alert-sucess':'alert-danger'//boootstrap框架
        myAlert.classList.add(bgStyle)
        // 过两秒隐藏
        setTimeout(()=>{
          myAlert.classList.remove('show')
          // 避免类冲突,重置背景色
          myAlert.classList.remove(bgStyle)
        },2000)
      }

    document.querySelector('.btn-login').addEventListener('cilck',()=>{
      const username=document.querySelector('.username').value
      const password=document.querySelector('.password').value
      // 1.3判断长度
      if(username.length<8){
        alertFn('用户名必须大于8位',false)
        console.log('用户名必须大于等于8位')
        return//组织代码继续执行
      }
      if(password.length<6){
        alertFn('密码必须大于等于6位',false)
        console.log('密码必须大于等于6位')
        return//阻止代码继续执行
      }
      //基于axios提交用户名和密码
      console.log('提交数据到服务器')
      axios({
        url:'http://hmajax.itheima.net/api/login',
        method:'POST',
        data:{
          username,
          password
        }
      }).then(result=>{
        // console.log(result)
        alertFn(result.data.message,true)
        console.log(result.data.message)
      }).catch(error=>{
        console.log(error)
        console.log(error.response.data.message)//用户名或密码错误
      })
    })

form-serialize插件

作用:快速收集表单元素的值

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <form action="javascript:;" class="example-form">
    <input type="text" name="uname">
    <br>
    <input type="text" name="pwd">
    <br>
    <input type="button" value="提交" class="btn">
  </form>
  <!-- 在点击提交时,使用form-serialize插件,快速收集表单元素值
   -->
   <script src="./lib/form-serialize.js"></script>
   <script>
    document.querySelector('.btn').addEventListener('click',()=>{
      /**
       * 使用serialize函数,快速收集表单元素的值
       * 参数1:要获取哪个表单的数据
       * 表单元素设置name属性 值会作为对象的属性名
       * 建议name属性的值,最好和接口文档的参数名一致
       * hash  设置获取数据结构
       *    - true JS对象(true)推荐
       *    - false 获取查询字符串url?后面传递的参数
       * empty 设置是否获取空值
       * - true:获取空值 推荐
       * - false:不获取空值
       * 参数2:配置对象
       */
      const form=document.querySelector('.example-form')
      // const data=serialize(form,{hash:true,empty:true})
      const data=serialize(form,{hash:false,empty:true})
      console.log(data)
    })
   </script>
</body>
</html>

hash:true

hash:false

 

使用form-serialilze插件获取用户登录中表单里的数据

    const form=document.querySelector('.login-form')
      const data=serialize(form,{hash:true,empty:true})
      const {username,password}=data//解构赋值
      // const username = document.querySelector('.username').value
      // const password = document.querySelector('.password').value
      // console.log(username, password)

 Bootstrap弹框的使用

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

步骤:

  1. 引入bootstrap.css和bootstrap.js
  2. 准备弹框标签,确认结构
  3. 通过自定义属性,控制弹框的显示和隐藏、

通过属性设置,弹框的显示或隐藏(单纯显示和隐藏)

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

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

图书管理

自己的图书数据:给自己起个外号,并告诉服务器,默认会有三本书,基于这三本书做数据的增删改查

渲染图书列表

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

新增图书

/**
 * 目标2:新增图书
 *  2.1 新增弹框->显示和隐藏
 *  2.2 收集表单数据,并提交到服务器保存
 *  2.3 刷新图书列表
 */
// 2.1 创建弹框对象
const addModalDom = document.querySelector('.add-modal')
const addModal = new bootstrap.Modal(addModalDom)//利用js代码来隐藏和显示
// 保存按钮->点击->隐藏弹框
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,//它用于将 bookObj 中的所有可迭代属性展开到新的对象中。这意味着新对象将包含 bookObj 中的所有键值对。
      creator
    }
  }).then(result => {
    // console.log(result)
    // 2.3 添加成功后,重新请求并渲染图书列表
    getBooksList()
    // 重置表单
    addForm.reset()
    // 隐藏弹框
    addModal.hide()
  })
})

删除图书

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

编辑图书

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

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>

图片上传

  1. 获取图片文件对象
  2. 使用FormData携带图片文件
  3. 提交表单数据到服务器,使用图片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>图片上传</title>
</head>

<body>
  <!-- 文件选择元素 -->
  <input type="file" class="upload">
  <img src="" alt="" class="my-img">

  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    /**
     * 目标:图片上传,显示到网页上
     *  1. 获取图片文件
     *  2. 使用 FormData 携带图片文件
     *  3. 提交到服务器,获取图片url网址使用
    */
    // 文件选择元素->change改变事件
    document.querySelector('.upload').addEventListener('change', e => {
      // 1. 获取图片文件
      console.log(e.target.files[0])
      // 2. 使用 FormData 携带图片文件
      const fd = new FormData()
      fd.append('img', e.target.files[0])
      // 3. 提交到服务器,获取图片url网址使用
      axios({
        url: 'http://hmajax.itheima.net/api/uploadimg',
        method: 'POST',
        data: fd
      }).then(result => {
        console.log(result)
        // 取出图片url网址,用img标签加载显示
        const imgUrl = result.data.data.url
        document.querySelector('.my-img').src = imgUrl
      })
    })
  </script>
</body>

</html>

input file类型的change事件

input元素的file类型允许用户从他们的设备上选择一个或多个文件。当用户选择了文件(或者修改了已选择的文件)后,change事件就会被触发。这意味着如果用户通过点击文件输入框并选择了文件,或者拖拽文件到文件输入区域,change事件监听器就会执行。

FormData

FormData 是一个 JavaScript 内建对象,它主要用于构造一组键值对的数据集合,用以发送 HTTP 请求。这个对象特别适用于发送表单数据,无论是作为 AJAX 请求还是使用 Fetch API 发送数据到服务器,尤其是当涉及到文件上传时。以下是关于 FormData 的一些关键特点和使用方法:

特点:

  1. 自动构建请求体FormData 会根据给定的数据自动构建合适的请求体(Content-Type),这使得它在处理表单数据时非常方便,尤其是当涉及文件上传时,它会正确地设置 multipart/form-data 编码。
  2. 兼容性:支持现代浏览器,包括 IE10+,对于旧版浏览器,可能需要polyfill。
  3. 无需序列化:与传统的 XMLHttpRequest 发送表单数据时需要手动序列化不同,FormData 自动处理这一过程。
  4. 文件上传:非常适合用于文件上传,因为它能够处理二进制数据。

基本用法:

创建实例:
let formData = new FormData();
添加数据:
// 添加文本字段
formData.append('key', 'value');

// 添加文件
let file = document.querySelector('input[type=file]').files[0];
formData.append('file', file);

// 添加多个值到同一个键
formData.append('multiValueKey', 'value1');
formData.append('multiValueKey', 'value2');
发送请求:

使用 XMLHttpRequestfetch 发送数据:

// 使用 XMLHttpRequest
let xhr = new XMLHttpRequest();
xhr.open('POST', '/api/upload', true);
xhr.send(formData);

// 使用 fetch
fetch('/api/upload', {
  method: 'POST',
  body: formData
})
then(response => response.json())
then(data => console.log(data))
catch(error => console.error('Error:', error));

注意事项:

  • 当从表单直接创建 FormData 实例时,表单中的所有字段(包括文件输入)会被自动添加到 FormData 中。
  • 可以通过 formData.get(key)formData.getAll(key)formData.has(key)formData.set(key, value)formData.delete(key) 等方法来操作数据。
  • 如果需要获取 FormData 中的所有键值对,可以使用 formData.entries() 方法配合迭代器遍历。

FormData 是处理表单数据和文件上传的强大工具,极大地简化了从前复杂的 AJAX 请求处理过程。

 更换网页背景图片

1.选择图片上传,设置body背景

2.上传成功时,保存url网址

3.网页运行后,获取url网址使用

/**
 * 目标:网站-更换背景
 *  1. 选择图片上传,设置body背景
 *  2. 上传成功时,"保存"图片url网址
 *  3. 网页运行后,"获取"url网址使用
 * */
//选择对应的input框绑定change事件
document.querySelector('.bg-ipt').addEventListener('change', e => {
  // 1. 选择图片上传,设置body背景
  console.log(e.target.files[0])
  const fd = new FormData()
  fd.append('img', e.target.files[0])
  axios({
    url: 'http://hmajax.itheima.net/api/uploadimg',
    method: 'POST',
    data: fd
  }).then(result => {
    const imgUrl = result.data.data.url
    document.body.style.backgroundImage = `url(${imgUrl})`

    // 2. 上传成功时,"保存"图片url网址
    localStorage.setItem('bgImg', imgUrl)
  })
})

// 3. 网页运行后,"获取"url网址使用
const bgUrl = localStorage.getItem('bgImg')
console.log(bgUrl)
// 本地有背景图才设置
bgUrl && (document.body.style.backgroundImage = `url(${bgUrl})`)

个人信息设置

步骤:

1.信息渲染

2.头像修改

3.提交表单

4.结果提示

信息渲染

自己的用户信息:给自己起个外号,并告诉服务器,获取对应的用户信息

/**
 * 目标1:信息渲染
 *  1.1 获取用户的数据
 *  1.2 回显数据到标签上
 * */
const creator = '播仔'
// 1.1 获取用户的数据
axios({
  url: 'http://hmajax.itheima.net/api/settings',
  params: {
    creator
  }
}).then(result => {
  const userObj = result.data.data
  // 1.2 回显数据到标签上
  Object.keys(userObj).forEach(key => {
    if (key === 'avatar') {
      // 赋予默认头像
      document.querySelector('.prew').src = userObj[key]
    } else if (key === 'gender') {//gender和头像不可通过value来改变,只有表单元素才可通过foreach来改变
      // 赋予默认性别
      // 获取性别单选框:[男radio元素,女radio元素]
      const gRadioList = document.querySelectorAll('.gender')
      // 获取性别数字:0男,1女
      const gNum = userObj[key]
      // 通过性别数字,作为下标,找到对应性别单选框,设置选中状态
      gRadioList[gNum].checked = true
    } else {
      // 赋予默认内容
      document.querySelector(`.${key}`).value = userObj[key]
    }
  })
})

头像修改

/**
 * 目标2:修改头像
 *  2.1 获取头像文件
 *  2.2 提交服务器并更新头像
 * */
// 文件选择元素->change事件
document.querySelector('.upload').addEventListener('change', e => {
  // 2.1 获取头像文件
  console.log(e.target.files[0])
  const fd = new FormData()
  fd.append('avatar', e.target.files[0])
  fd.append('creator', creator)
  // 2.2 提交服务器并更新头像
  axios({
    url: 'http://hmajax.itheima.net/api/avatar',
    method: 'PUT',
    data: fd
  }).then(result => {
    const imgUrl = result.data.data.avatar
    // 把新的头像回显到页面上
    document.querySelector('.prew').src = imgUrl
  })
})

提交表单(信息修改)

结果提示

给div盒子添加类名toast,会出现提示框

/**
 * 目标4:结果提示
 *  4.1 创建toast对象
 *  4.2 调用show方法->显示提示框
 */
// 保存修改->点击
document.querySelector('.submit').addEventListener('click', () => {
  // 3.1 收集表单信息
  const userForm = document.querySelector('.user-form')
  const userObj = serialize(userForm, { hash: true, empty: true })
  userObj.creator = creator
  // 性别数字字符串,转成数字类型
  userObj.gender = +userObj.gender
  console.log(userObj)
  // 3.2 提交到服务器保存
  axios({
    url: 'http://hmajax.itheima.net/api/settings',
    method: 'PUT',
    data: userObj//aixos会自动将对象转化为JSON字符串
  }).then(result => {
    // 4.1 创建toast对象
    const toastDom = document.querySelector('.my-toast')
    const toast = new bootstrap.Toast(toastDom)

    // 4.2 调用show方法->显示提示框
    toast.show()
  })
})

AJAX原理 - XMLHttpRequest

定义:XMLHttpRequest(XHR)对象用于与服务器进行交互,通过XMLHttpRequest可以在不刷新页面的情况下请求特定URL,获取数据,这允许网页在不影响用户操作的情况下,更新页面的局部内容,XMLHttpRequest在AJAX编程中被大量使用

关系:axios内部采用XMLHttpRequest与服务器进行交互

好处:掌握使用XHR与服务器进行数据交互,了解axios内部原理

使用XMLHttpRequest

需求:获取并展示所有省份名字

    /**
     * 目标:使用XMLHttpRequest对象与服务器通信
     *  1. 创建 XMLHttpRequest 对象
     *  2. 配置请求方法和请求 url 地址
     *  3. 监听 loadend 事件,接收响应结果
     *  4. 发起请求
    */
    // 1. 创建 XMLHttpRequest 对象
    const xhr = new XMLHttpRequest()

    // 2. 配置请求方法和请求 url 地址
    xhr.open('GET', 'http://hmajax.itheima.net/api/province')

    // 3. 监听 loadend 事件,接收响应结果,loadend无论成功还是失败,都会执行后面的函数
    xhr.addEventListener('loadend', () => {
      console.log(xhr.response)
      const data = JSON.parse(xhr.response)
      console.log(data.list.join('<br>'))
      document.querySelector('.my-p').innerHTML = data.list.join('<br>')
    })

    // 4. 发起请求
    xhr.send()

XHR使用步骤:

  • 创建XHR对象
  • 调用open方法,设置url和请求方法
  • 监听loadend事件,接收结果
  • 调用send方法,发起请求

 XMLHttpRequest- 查询参数

定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据

语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2

    /**
     * 目标:使用XHR携带查询参数,展示某个省下属的城市列表
    */
    const xhr = new XMLHttpRequest()
    xhr.open('GET', 'http://hmajax.itheima.net/api/city?pname=辽宁省')
    xhr.addEventListener('loadend', () => {
      console.log(xhr.response)
      const data = JSON.parse(xhr.response)
      console.log(data)
      document.querySelector('.city-p').innerHTML = data.list.join('<br>')
    })
    xhr.send()

地区查询

需求:输入省份和城市名字,查询地区列表

请求地址:http://hmajax.itheima.net/api/area?参数名=值1&参数名=值2

    /**
     * 目标: 根据省份和城市名字, 查询对应的地区列表
    */
    // 1. 查询按钮-点击事件
    document.querySelector('.sel-btn').addEventListener('click', () => {
      // 2. 收集省份和城市名字
      const pname = document.querySelector('.province').value
      const cname = document.querySelector('.city').value

      // 3. 组织查询参数字符串
      const qObj = {
        pname,
        cname
      }
      // 查询参数对象 -> 查询参数字符串
      const paramsObj = new URLSearchParams(qObj)
      const queryString = paramsObj.toString()
      console.log(queryString)

      // 4. 使用XHR对象,查询地区列表
      const xhr = new XMLHttpRequest()
      xhr.open('GET', `http://hmajax.itheima.net/api/area?${queryString}`)
      xhr.addEventListener('loadend', () => {
        console.log(xhr.response)
        const data = JSON.parse(xhr.response)
        console.log(data)
        const htmlStr = data.list.map(areaName => {
          return `<li class="list-group-item">${areaName}</li>`
        }).join('')
        console.log(htmlStr)
        document.querySelector('.list-group').innerHTML = htmlStr
      })
      xhr.send()
    })

XMLHttpRequest - 数据提交

需求:通过XHR提交用户名和密码,完成注册功能

核心:

  • 请求头设置Content - Type:application/json
  • 请求体携带JSON字符串
  <button class="reg-btn">注册用户</button>
  <script>
    /**
     * 目标:使用xhr进行数据提交-完成注册功能
    */
    document.querySelector('.reg-btn').addEventListener('click', () => {
      const xhr = new XMLHttpRequest()
      xhr.open('POST', 'http://hmajax.itheima.net/api/register')
      xhr.addEventListener('loadend', () => {
        console.log(xhr.response)
      })

      // 设置请求头-告诉服务器内容类型(JSON字符串)
      xhr.setRequestHeader('Content-Type', 'application/json')
      // 准备提交的数据
      const userObj = {
        username: 'itheima007',
        password: '7654321'
      }
      const userStr = JSON.stringify(userObj)
      // 设置请求体,发起请求
      xhr.send(userStr)
    })
  </script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1666930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

echarts环形图 legend文字过长显示...鼠标移动上展示全称

legend: {type: scroll,orient: vertical,x: left,y: bottom,top: "42%",left: 13%,data: this.dutyNames,textStyle: { color: #fff },triggerEvent: true,tooltip: {show: true,trigger: item,//鼠标移动上去展示全称},formatter: function (params) {var val &qu…

构建一个快速数据分析(boruta+shap+rcs)的shiny APP

构建一个快速数据分析&#xff08;borutashaprcs&#xff09;的shiny APP 之前提出了一个快速数据分析的流程&#xff0c;包括&#xff1a; 变量筛选&#xff0c;使用Boruta等变量筛选的方法来找出相关的变量&#xff1b;发现规律&#xff0c;使用SHAP分析的散点图、交互作用图…

微服务思想以及实现

文章目录 前言一、什么时候需要拆分微服务1. 创业型项目2. 大型项目 二、怎么拆1. 拆分目标2. 拆分方式 三、微服务之间远程调用1. 实现方式2. 手动发送Http请求&#xff08;RestTemplate&#xff09;3. 服务注册中心3.1 原理3.2 Nacos注册中心3.3 服务注册3.4 服务发现(Discov…

牛客网Java实战项目--仿牛客网社区的学习笔记

仿牛客网社区的学习笔记 1. 项目环境搭建1.1 开发社区首页 2.开发社区登录模块2.1 发送邮件2.2 开发注册功能2.3 会话管理2.4 生成验证码2.5 开发登录、退出功能2.6 显示登录信息 4 Redis实现点赞关注4.1 Spring整合Redis访问Redis的方法&#xff1a; 4.2 Redis实现点赞4.2.1 点…

【图解计算机网络】http1.1,http2.0,http3.0

http1.1&#xff0c;http2.0&#xff0c;http3.0 http1.1长连接管道传输缺点 http2.0头部压缩二进制格式并发传输服务端推送缺点 http3.0无队头阻塞快速建立连接连接迁移 http1.1 长连接 在http1.0的时候&#xff0c;一次http请求就要建立一次TCP连接&#xff0c;这一次的htt…

【计算机网络篇】数据链路层(10)在物理层扩展以太网

文章目录 &#x1f354;扩展站点与集线器之间的距离&#x1f6f8;扩展共享式以太网的覆盖范围和站点数量 &#x1f354;扩展站点与集线器之间的距离 &#x1f6f8;扩展共享式以太网的覆盖范围和站点数量 以太网集线器一般具有8~32个接口&#xff0c;如果要连接的站点数量超过了…

【busybox记录】【shell指令】ls

目录 内容来源&#xff1a; 【GUN】【ls】指令介绍 【busybox】【ls】指令介绍 【linux】【ls】指令介绍 使用示例-默认输出&#xff1a; 列出目录内容 - 默认输出 列出目录内容 - 不忽略以.开头的文件 列出目录内容 - 不忽略以.开头的文件&#xff0c;只忽略.和..文件…

使用Maven对Java独立应用程序进行编译打包

一、 安装Maven 1.解压&#xff0c;移动安装包 sudo tar -zxf ~/apache-maven-3.9.6-bin.tar.gz -C /usr/local/ cd /usr/local/ sudo mv apache-maven-3.9.6/ ./maven-3.9.6 sudo chown -R qiangzi ./maven-3.9.6 二、Java应用程序代码 1.版本信息&#xff1a; Spark-2.1…

picoCTF-Web Exploitation-More SQLi

Description Can you find the flag on this website. Additional details will be available after launching your challenge instance. Hints SQLiLite 先随便输入个账号密码登录一下&#xff0c;得到查询SQL&#xff0c;接下来应该对SQL进行某些攻击来绕过密码登录成功 -- …

如何自定义Linux命令

说明&#xff1a;本文介绍如何将自己常用的命令设置为自定义的命令&#xff0c;以下操作在阿里云服务器CentOS上进行。 修改配置文件 修改配置文件前&#xff0c;先敲下面的命令查看当前系统配置的shell版本 echo $SHELL或者 echo $0区别在于&#xff0c;$SHELL查看的是系统…

【Shell】shell编程之循环语句

目录 1.for循环 例题 2.while循环 例题 3.until循环 1.for循环 读取不同的变量值&#xff0c;用来逐个执行同一组命令 for 变量 in 取值列表 do 命令序列 done [rootlocalhost ~]# for i in 1 2 3 > do > echo "第 $i 次跳舞" > done 第 1 次跳舞 第 …

java基础之面向对象的思想

一、面向对象和面向过程的编程思想对比 面向过程&#xff1a;是一种以过程为中心的编程思想&#xff0c;实现功能的每一步&#xff0c;都是自己实现的&#xff08;自己干活&#xff09;。 面向对象&#xff1a;是一种以对象为中心的编程思想&#xff0c;通过指挥对象实现具体的…

5. 简单说一说uniapp中的语法吧

前言 如果你 知道Vue3并且对Vue3的语法有一定了解&#xff0c;请跳过这一章&#xff0c;由于后续项目主要是基于Vue3TypeScript&#xff0c;因此提前简单概述一些Vue3的基础语法~ 本文的目的是 期望通过对本文的阅读后能对Vue3的每个语法有一个简单的印象&#xff0c;至少要知…

【Linux】动态库与静态库的底层比较

送给大家一句话&#xff1a; 人生最遗憾的&#xff0c;莫过于&#xff0c;轻易地放弃了不该放弃的&#xff0c;固执地坚持了不该坚持的。 – 柏拉图 (x(x_(x_x(O_o)x_x)_x)x) (x(x_(x_x(O_o)x_x)_x)x) (x(x_(x_x(O_o)x_x)_x)x) 底层比较 1 前言2 编译使用比较2 如何加载Than…

连升三级!openGauss单机版从2.1.0经停3.0.0升级至5.0.0

前言 如前文所述&#xff0c;我们的小demo项目起初安装了openGauss的2.1.0版本&#xff0c;由于2.1.0不是长期维护&#xff08;LTS&#xff09;版本&#xff0c;所以要升级到5.0.0LTS。考虑到虽然是DEMO项目&#xff0c;但也有些体验用户&#xff0c;所以为了保障业务连续性&a…

网络基础-Telnet协议

Telnet&#xff08;Telecommunication Network&#xff09;是一种基于文本的远程终端协议&#xff0c;允许用户通过网络连接到远程计算机&#xff0c;并在远程计算机上执行命令&#xff1b;它使用TCP作为传输层协议&#xff0c;并依赖于网络连接在客户端和服务器之间进行通信&a…

商务分析方法与工具(九):Python的趣味快捷-Pandas处理公司财务数据集思路

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

Linux部署

先把需要的东西准备好&#xff1a; 第一步解压tomcat&#xff1a; tar -zxvf apache-tomcat-8.5.20.tar.gz 第二步解压jdk: tar -zxvf jdk-8u151-linux-x64.tar.gz 第三步配置Java环境变量&#xff1a; vim /etc/profile 把下面代码放进去&#xff1a; export JAVA_HOME/root…

定时任务的几种实现方式

定时任务实现的几种方式&#xff1a; 1、JDK自带 &#xff08;1&#xff09;Timer&#xff1a;这是java自带的java.util.Timer类&#xff0c;这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行&#xff0c;但不能在指定时间运行。…

基于SpringBoot+Vue社区老人健康信息管理系统

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统社区老人健康信息管理系统信息管理难度大&#xff0c;容错…