AJAX day4 英雄管理案例

954 阅读5分钟

英雄管理案例

0.前期工作

添加axios的全局配置

主要是配置根路径:axios.defaults.baseURL = 'http://127.0.0.1:3001'

设置全局配置

首先,创建一个utils文件夹,在里面创建一个request.js文件,在文件里面设置全局配置

axios.defaults.baseURL = 'http://127.0.0.1:3001'

创建index.js文件

在网页文件引入外部资源

<!-- bootstrap资源文件,它要基于jquery -->
  <script src="./libs/bootstrap/js/bootstrap.min.js"></script>
  <!-- 引入axios文件 -->
  <script src="./libs/axios.js"></script>
  <!-- 引入全局配置 -->
  <script src="./utils/request.js"></script>
  <!-- 引入index -->
  <script src="./js/index.js"></script><!-- 注意:引入资源的顺序一定要留心,先有axios插件,再引入全局配置,最后才是引入自己的index文件,否则全局配置不起效,到时会报错 -->

1.实现数据动态渲染

动态数据的渲染,封装函数,遍历拼接,渲染一定要准备好静态结构和数据

  1. 获取元素
  2. 发起ajax请求,请求路径:/getHeroList
  3. 封装为一个函数
  4. 对数据进行遍历拼接
// 获取元素
let tbody = document.querySelector('tbody')
// 1.数据渲染
function init(){
  axios({
    // method默认为'get',所以此处可省略
    url: '/getHeroList',
  }).then(res => {
    console.log(res)
    let htmlStr = ''
    res.data.data.forEach(function(value,index){
      htmlStr += `<tr>
                    <td>${index + 1}</td>
                    <td>${value.name}</td>
                    <td>${value.gender}</td>
                    <td>
                      <img src="${value.img}" alt="" />
                    </td>
                    <td>
                      <button type="button" class="btn btn-info imgUpload" data-id='${value.id}'>
                        上传头像
                      </button>
                      <button type="button" class="btn btn-warning btndel" data-id="${value.id}">
                        删除
                      </button>
                    </td>
                  </tr>`
    })
    tbody.innerHTML = htmlStr
  })
}
init()

2.实现数据搜索--查询

查询,搜索和渲染本质上都是查询 ,意味着共享同一个方法

  1. 获取元素,绑定事件,在事件处理函数中获取用户输入的内容,实现搜索
  2. 获取用户输入内容
  3. 调用init方法,添加一个参数,参数就是搜索关键字
  4. 在axios请求的配置选项中添加params选项,用于参数的设置
  5. 细节:是否有查询参数,没有传递参数就查询所有值,如果有参数就根据参数进行查询
// 获取元素
let btn_search = document.querySelector('#btn_search')
let hname = document.querySelector('#hname')
function init(heroName){
  axios({
    url: '/getHeroList',
    params: { heroName }
  }).then(res => {
    console.log(res)
    let htmlStr = ''
    res.data.data.forEach(function(value,index){
      htmlStr += `<tr>
                    <td>${index + 1}</td>
                    <td>${value.name}</td>
                    <td>${value.gender}</td>
                    <td>
                      <img src="${value.img}" alt="" />
                    </td>
                    <td>
                      <button type="button" class="btn btn-info imgUpload" data-id='${value.id}'>
                        上传头像
                      </button>
                      <button type="button" class="btn btn-warning btndel" data-id="${value.id}">
                        删除
                      </button>
                    </td>
                  </tr>`
    })
    tbody.innerHTML = htmlStr
  })
}
init()
// 2.搜索实现
btn_search.addEventListener('click', function(){
  // 获取输入框的值,作为参数传递给封装的函数
  let key = hname.value
  init(key)
})

3.添加英雄数据

3.1 弹出新增模态框

  1. 获取元素
  2. 单击“新增”按钮,需要弹出模态框
  3. 使用jq的方法:$('#addHeroModal').modal('show')
let btn_search = document.querySelector('#btn_search')
let hname = document.querySelector('#hname')
// 获取模态框元素
let openDialog = document.querySelector('.openDialog')
let heroname = document.querySelector('#heroname')
let herogender = document.querySelector('#gender')
let btnAdd = document.querySelector('.btnAdd')
// 3.1弹出新增模态框
openDialog.addEventListener('click',function(){
  $('#addHeroModal').modal('show')
})

3.2 实现新增功能

需求:弹出模态框后,在输入框中输入英雄信息后,单击确认按钮,实现英雄数据的新增

  1. 收集用户数据,收集方式有三种方法:(1)一个一个收集:获取元素,获取元素的value值 (2)serialize()方法(3)formadata方法
  2. 发起ajax请求,请求方式:post,请求地址:/addHero,请求参数name,gender,img,因为参数比较少,我们选择第一种收集方式,参数只能是key=value&key1=value1
  3. 请求成功后,给出提示,隐藏模态框,重新渲染,清空之前的内容
// 3.2实现新增功能
btnAdd.addEventListener('click',function(){
  let name = heroname.value
  let gender = herogender.value
  // js中的文件的路径参照 不是参照当前js的文件,而是参照引入这个js文件的页面
  let img = './images/default.jpg'
  axios({
    method: 'post',
    url: '/addHero',
    // 参数格式只能写key=value&key1=value1
    data: `name=${name}&gender=${gender}&img=${img}`
    // data: { name, gender, img }  错误演示
  }).then(res => {
    console.log(res);
    if(res.data.code == 200){
      alert(res.data.msg)
      $('#addHeroModal').modal('hide')
      init()
      heroname.value = ''
      herogender.value = '男'
    }
  })
})
重点细节

新增接口的参数只支持key=value&key=value

新增面板中没有图片,所以我们可以为其设置一个默认值

4.实现删除功能

动态元素的事件绑定使用事件委托

  1. 要判断是否操作指定的元素
  2. 可以添加一个判断语句是否确定删除,如果不删可以取消,这样可以防止误删
  3. 发起ajax请求,请求方式:get,请求地址:/delHeroById,请求参数:id
  4. 由于参数是id,删除需要传入 英雄id 做为条件,现存再取,为删除按钮添加自定义属性id,通过元素.dataset获取id
  5. 删除成功后,给出提示,重新渲染
// 4.实现删除功能
tbody.addEventListener('click', function(e){
  // 判断是否单击了删除按钮
  if(e.target.classList.contains('btndel')){
    // 弹出是否确定删除确认框
    if(confirm("你确定要删除吗?")){
      let id = e.target.dataset.id
      axios({
        url: '/delHeroById',
        params: { id }
      }).then(res => {
        console.log(res);
        if(res.data.code == 200){
          alert(res.data.msg)
          init()
        }
      })
    }
  }
})

5.实现文件上传

5.1 弹出文件上传模态框

使用事件委托的方式绑定事件

判断单击的是否是上传文件按钮

// 获取文件上传元素
let btnHeroEdit = document.querySelector('.btnHeroEdit')
let heroImg = document.querySelector('#heroImg')
// 5.实现文件上传
let editId;
// 5.1 弹出文件上传模态框
tbody.addEventListener('click', function(e){
  // 判断单击的是上传文件按钮
  if(e.target.classList.contains('imgUpload')){
    $('#uploadImgModal').modal('show')
    editId = e.target.dataset.id
  }
})

5.2 实现用户头像的更新

  1. 获取文件对象
  2. 创建formdata对象,通过formdata收集文件数据,new FormData(form表单元素)
  3. 将文件对象追加到formdata中,formdata.append(键,文件对象),发起ajax请求,formdata可以直接做为参数传递
  4. 发起ajax请求实现文件上传
  5. 当文件上传成功之后,还需要更新用户的头像信息,接口要求传递数据id,先存再取,在弹出模态框时,获取id的值
  6. 更新头像还需要传递头像路径,这个路径就是来自于文件上传成功之后的返回数据
// 5.2 实现文件上传的功能
btnHeroEdit.addEventListener('click', function(){
  // 获取文件对象
  let myfile = heroImg.files[0]
  // 创建formdata对象
  let formdata = new FormData()
  // 将文件对象追加到formdata中
  formdata.append('file_data', myfile)
  // 判断是否选择了文件
  if(heroImg.value = ''){
    alert('请选择文件')
    return
  }
  // 发起ajax请求实现文件上传
  axios({
    method: 'post',
    url: '/uploadFile',
    data: formdata
  }).then(res => {
    console.log(res);
    if(res.data.code == 200){
      alert(res.data.msg)
      // 再发起ajax请求实现用户头像更新
      axios({
        method: 'post',
        url: '/updateHero',
        data: `id=${editId}&img=${res.data.src}`
      }).then(result => {
        console.log(result);
        if(result.data.code == 200){
          alert(result.data.msg)
          $('#uploadImgModal').modal('hide')
          init()
          heroImg.value = ''
        }
      })
    }
  })
})

完成代码结构

HTML代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>英雄管理</title>
    <link rel="stylesheet" href="./libs/bootstrap/css/bootstrap.min.css" />
    <style>
      .panel {
        width: 900px;
        margin: 10px auto;
      }

      .table img {
        width: 40px;
        height: 40px;
      }
    </style>
  </head>

  <body>
    <div class="container">
      <div class="panel panel-primary">
        <div class="panel-heading">英雄列表管理</div>
        <div class="panel-body">
          <div class="row">
            <div class="col-lg-6">
              <div class="input-group">
                <input
                  type="text"
                  id="hname"
                  class="form-control"
                  placeholder="输入英雄信息..."
                  autocomplete="true"
                />
                <span class="input-group-btn">
                  <button class="btn btn-default" id="btn_search" type="button">
                    搜索
                  </button>
                </span>
              </div>
            </div>

            <div class="col-lg-3 col-lg-offset-3">
              <button type="button" class="btn btn-success openDialog">
                添加英雄
              </button>
            </div>
          </div>
        </div>

        <table class="table">
          <thead>
            <tr>
              <th>编号</th>
              <th>英雄名称</th>
              <th>英雄性别</th>
              <th>头像</th>
              <th>操作区</th>
            </tr>
          </thead>
          <!-- 表格主体 -->
          <tbody id="tbody">
            <!-- <tr>
              <td>1</td>
              <td>74期小伙伴</td>
              <td>男/女</td>
              <td>
                <img src="./images/default.jpg" alt="" />
              </td>
              <td>
                <button type="button" class="btn btn-info">
                  上传头像
                </button>
                <button type="button" class="btn btn-warning">
                  删除
                </button>
              </td>
            </tr> -->
          </tbody>
        </table>
      </div>
    </div>
    <!-- 新增英雄模态框 -->
    <div class="modal fade" id="addHeroModal" tabindex="-1" role="dialog">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <button
              type="button"
              class="close"
              data-dismiss="modal"
              aria-label="Close"
            >
              <span aria-hidden="true">&times;</span>
            </button>
            <h4 class="modal-title">添加英雄</h4>
          </div>
          <div class="modal-body">
            <form class="form-horizontal">
              <div class="form-group">
                <label for="heroname" class="col-sm-2 control-label"
                  >英雄名称</label
                >
                <div class="col-sm-10">
                  <input
                    type="text"
                    class="form-control"
                    id="heroname"
                    placeholder="请输入英雄名称"
                    name="name"
                  />
                </div>
              </div>
              <div class="form-group">
                <label for="gender" class="col-sm-2 control-label"
                  >英雄性别</label
                >
                <div class="col-sm-10">
                  <!-- 对于下拉列表,如果option没有设置 value属性,就获取option之间的内容,如果有value属性就获取value属性 -->
                  <select class="form-control" id="gender" name="gender">
                    <option></option>
                    <option></option>
                  </select>
                </div>
              </div>
            </form>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">
              取消
            </button>
            <button type="button" class="btn btn-success btnAdd">确定</button>
          </div>
        </div>
      </div>
    </div>
    <!-- 上传文件的模态框 -->
    <div
      class="modal fade"
      id="uploadImgModal"
      tabindex="-1"
      role="dialog"
      aria-labelledby="myModalLabel"
    >
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <button
              type="button"
              class="close"
              data-dismiss="modal"
              aria-label="Close"
            >
              <span aria-hidden="true">&times;</span>
            </button>
            <h4 class="modal-title" id="myModalLabel">上传头像</h4>
          </div>
          <div class="modal-body">
            <input type="file" id="heroImg" />
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">
              取消
            </button>
            <button type="button" class="btn btn-primary btnHeroEdit">
              确定
            </button>
          </div>
        </div>
      </div>
    </div>

    <script src="./libs/jquery/jquery.min.js"></script>
    <!-- bootstrap资源文件,它要基于jquery -->
    <script src="./libs/bootstrap/js/bootstrap.min.js"></script>
    <!-- 引入axios文件 -->
    <script src="./libs/axios.js"></script>
    <!-- 引入全局的配置文件 -->
    <script src="./utils/request.js"></script>
    <!-- 引入页面的js文件 -->
    <script src="./js/index copy 2.js"></script>
  </body>
</html>
// 获取表格结构元素
let tbody = document.querySelector('tbody')
let btn_search = document.querySelector('#btn_search')
let hname = document.querySelector('#hname')
// 获取模态框元素
let openDialog = document.querySelector('.openDialog')
let heroname = document.querySelector('#heroname')
let herogender = document.querySelector('#gender')
let btnAdd = document.querySelector('.btnAdd')
// 获取文件上传元素
let btnHeroEdit = document.querySelector('.btnHeroEdit')
let heroImg = document.querySelector('#heroImg')
// 1.数据渲染
function init(heroName){
  axios({
    url: '/getHeroList',
    params: { heroName }
  }).then(res => {
    console.log(res)
    let htmlStr = ''
    res.data.data.forEach(function(value,index){
      htmlStr += `<tr>
                    <td>${index + 1}</td>
                    <td>${value.name}</td>
                    <td>${value.gender}</td>
                    <td>
                      <img src="${value.img}" alt="" />
                    </td>
                    <td>
                      <button type="button" class="btn btn-info imgUpload" data-id='${value.id}'>
                        上传头像
                      </button>
                      <button type="button" class="btn btn-warning btndel" data-id="${value.id}">
                        删除
                      </button>
                    </td>
                  </tr>`
    })
    tbody.innerHTML = htmlStr
  })
}
init()

// 2.搜索实现
btn_search.addEventListener('click', function(){
  // 获取输入框的值,作为参数传递给封装的函数
  let key = hname.value
  init(key)
})

// 3.新增英雄数据
// 3.1弹出新增模态框
openDialog.addEventListener('click',function(){
  $('#addHeroModal').modal('show')
})
// 3.2实现新增功能
btnAdd.addEventListener('click',function(){
  let name = heroname.value
  let gender = herogender.value
  // js中的文件的路径参照 不是参照当前js的文件,而是参照引入这个js文件的页面
  let img = './images/default.jpg'
  axios({
    method: 'post',
    url: '/addHero',
    // 参数格式只能写key=value&key1=value1
    data: `name=${name}&gender=${gender}&img=${img}`
    // data: { name, gender, img }  错误演示
  }).then(res => {
    console.log(res);
    if(res.data.code == 200){
      alert(res.data.msg)
      $('#addHeroModal').modal('hide')
      init()
      heroname.value = ''
      herogender.value = '男'
    }
  })
})

// 4.实现删除功能
tbody.addEventListener('click', function(e){
  // 判断是否单击了删除按钮
  if(e.target.classList.contains('btndel')){
    // 弹出是否确定删除确认框
    if(confirm("你确定要删除吗?")){
      let id = e.target.dataset.id
      axios({
        url: '/delHeroById',
        params: { id }
      }).then(res => {
        console.log(res);
        if(res.data.code == 200){
          alert(res.data.msg)
          init()
        }
      })
    }
  }
})

// 5.实现文件上传
let editId;
// 5.1 弹出文件上传模态框
tbody.addEventListener('click', function(e){
  // 判断单击的是上传文件按钮
  if(e.target.classList.contains('imgUpload')){
    $('#uploadImgModal').modal('show')
    editId = e.target.dataset.id
  }
})
// 5.2 实现文件上传的功能
btnHeroEdit.addEventListener('click', function(){
  // 获取文件对象
  let myfile = heroImg.files[0]
  // 创建formdata对象
  let formdata = new FormData()
  // 将文件对象追加到formdata中
  formdata.append('file_data', myfile)
  // 判断是否选择了文件
  if(heroImg.value = ''){
    alert('请选择文件')
    return
  }
  // 发起ajax请求实现文件上传
  axios({
    method: 'post',
    url: '/uploadFile',
    data: formdata
  }).then(res => {
    console.log(res);
    if(res.data.code == 200){
      alert(res.data.msg)
      // 再发起ajax请求实现用户头像更新
      axios({
        method: 'post',
        url: '/updateHero',
        data: `id=${editId}&img=${res.data.src}`
      }).then(result => {
        console.log(result);
        if(result.data.code == 200){
          alert(result.data.msg)
          $('#uploadImgModal').modal('hide')
          init()
          heroImg.value = ''
        }
      })
    }
  })
})