Ajax--英雄案例,基本诠释了ajax的使用,包括增、删、改、查和文件上传

91 阅读5分钟

英雄案例

目标

回顾ajax方法的使用

数据动态渲染的流程

体会ajax可以实现页面的局部刷新

掌握数据的完整的增加删除修改和查询

了解模态框的使用

初步理解数据操作的细节

整个页面效果是基于bootstrap

实现数据的动态渲染

静态结构 》 查阅接口文档 》 ajax请求获取数据 》分析数据 》 拼接生成动态结构(模板引擎) 》填充到指定位置

页面一加载就需要发起请求获取数据,实现动态渲染

查阅接口文档

02-英雄信息管理 - 1获取所有英雄-Ajax课程 > http://127.0.0.1:3001/getHeroList

请求方式:get

请求参数:heroName,参数如果不传递则获取所有数据,如果传递则获取满足条件的数据

说明:数据渲染和查询本质都是查询,区别在于是否有条件

动态渲染

let tbody = this.document.querySelector('#tbody')
  // 1.实现数据的渲染--封装为一个函数,后期复用
  function init() {
    // 发起请求
    axios({
      url: 'http://127.0.0.1:3001/getHeroList'
    }).then(res => {
      let data = res.data.data
      // 遍历拼接
      let htmlStr = ''
      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">
                          上传头像
                        </button>
                        <button type="button" class="btn btn-warning">
                          删除
                        </button>
                      </td>
                    </tr>`
      })
      tbody.innerHTML = htmlStr
    })
  }
  init()

实现数据的查询

查询的本质也是数据获取

如果没有参数就是全部获取,如果有参数就是查询,本质上都是发起同一个请求,只是参数不一样,所以我们可以将获取数据的操作封装为一个函数,将用户关键字做为函数的参数

1.获取用户关键字

2.单击按钮,发起ajax请求,同时将用户关键字做为参数传递

代码实现

function init(key = '') {
    // 发起请求
    axios({
      url: 'http://127.0.0.1:3001/getHeroList',
      params: { heroName: key }
    }).then(res => {
      let data = res.data.data
      // 遍历拼接
      let htmlStr = ''
      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">
                          上传头像
                        </button>
                        <button type="button" class="btn btn-warning">
                          删除
                        </button>
                      </td>
                    </tr>`
      })
      tbody.innerHTML = htmlStr
    })
  }
  init()

  // 搜索也是查询操作(渲染,搜索,分页)
  btn_search.addEventListener('click', function() {
    let key = hname.value
    init(key)
  })

说明

1.为什么没有会参数时,也能正确的查询到所有值
答:因为任何字符串都包含空字符串

2.后台是如何实现查询业务的
答:后台是使用模糊查询,只要包含你输入的用户关键字,就能获取到对应的结果

英雄数据的新增

一:弹出模态框

  • 了解bootstrap文档的使用方式
  • 在页面中先添加一个模态框
  • 能够弹出模态框
  • 制作模态框

二:实现英雄数据的新增

  • 查阅接口文档,确定你需要收集的数据
  • 发起ajax请求
  • 。。。

添加新增英雄模态框

模态框应该做为body的直接子元素

不要同时弹出多个模态框

直接拷贝模态框的基本代码

打开模态框

  • data属性设置弹出模态框
    • data-toggle="modal":说明它是一个手风琴效果的模态框
    • data-target="#myModal":指定当前载体所关联的模态框
    • 说明:myModal就模态框的id,可以自定义
    • 在新增按钮中添加这两个属性
  • js方式弹出模态框
    • 有些场景,我们不仅仅只需要弹出模态框,而且还要进行其它的一些业务处理
    • 错误细节:如果发现模态框一闪而过,一般是因为你同时使用属性和js方式弹出同一个模态框

制作模态框

  • 模态框分为上中下三块结构,分别代码标题,内容,底部按钮
  • 主体内容的表单元素来自于 全局css样式 》 表单
  • 注册结构要闭合

模态框的添加

<!-- 新增英雄模态框 -->
<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="请输入英雄名称"
                                   />
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="gender" class="col-sm-2 control-label"
                               >英雄性别</label
                            >
                        <div class="col-sm-10">
                            <select class="form-control" id='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">确定</button>
            </div>
        </div>
    </div>
</div>

实现英雄的新增

  • 收集用户数据
  • 发起ajax请求

下拉列表的基本特性

整体说明:获取表单元素的值本质就是获取它的value值,对于下拉列表,一种是给用户看的值,一种是给程序员使用的值
- option标签之间的内容是给用户看值
- option的value属性是下拉列表选项的实际值

1.如果下拉列表的option选项没有设置value属性,则获取option标签之间的内容
2.如果下拉列表的option选项设置了value属性,则优先获取value属性的值

实现新增

btnAdd.addEventListener('click', function() {
    // 收集数据
    let name = heroname.value
    let gender = herogender.value

    // axios请求
    // axios({
    //   method: 'post',
    //   url: 'http://127.0.0.1:3001/addHero',
    //   data: `name=${name}&gender=${gender}`
    // })
    axios
      .post('http://127.0.0.1:3001/addHero', `name=${name}&gender=${gender}`)
      .then(res => {
        console.log(res)
        if (res.data.code == 200) {
          alert(res.data.msg)
          // 关闭模态框
          $('#addHeroModal').modal('hide')
          // 重新渲染
          init()
        }
      })
  })

英雄数据的删除

  • 查阅接口文档,我们发现接口文档明确告诉我们,删除数据的时候需要传入一个参数id--删除操作一定要考虑是否有条件,如果没有条件就会删除所有数据
  • 这个id就是能够唯一标识你想删除的数据
  • 所以,我们发现,删除最重新的前提是:获取当前你想删除的数据的id

事件绑定

动态生成的元素的事件绑定应该使用事件委托,因为异步非阻塞,所以直接为删除按钮绑定事件的时候,html结构还没有生成 ,所以才需要使用事件委托

// 实现英雄数据的删除
// 动态生成的元素的事件绑定需要使用事件委托
tbody.addEventListener('click', function(e) {
    if (e.target.classList.contains('btndel')) {
        axios({
            url: '/delHeroById',
            method: 'get',
            params: { id: e.target.dataset.id }
        }).then(res => {
            alert(res.data.msg)
            init()
        })
    }
})

实现删除操作

删除操作最关键的问题在于获取当前你想删除的数据的id

意味着:你做一个操作需要使用到一个变量(数据),那么

1.能传递参数就传递参数

2.如果不能传递参数就先存储再获取:如何存储,存储在那里?如何获取

  • 在渲染的时候,在删除按钮中添加自定义属性存储id

    <button type="button" class="btn btn-warning btndel" data-id='${value.id}'>
        删除
    </button>
    
    
  • 在单击“删除"按钮的时候,获取里面存储的id号

      
    

上传头像-编辑

添加编辑用户的模态框

为编辑按钮添加委托事件

这个操作的本质是编辑用户头像信息,所以它有两个操作

1.上传文件

2.更新用户信息--编辑操作

实现文件上传

  • 收集文件数据

    let myfile = document.querySelector('#heroImg').files[0]
    // 使用formdata收集文件数据
    let formdata = new FormData()
    // 键:后台接口的参数名称
    // 值:可以是任意类型的数据,当然也包含文件
    // formdata.append(键,值)
    // formdata.append('file_data',文件对象)
    formdata.append('file_data', myfile)
    
  • 发起ajax请求

     // 实现文件上传
      btnHeroEdit.addEventListener('click', function() {
        // 一:实现文件上传
        // 1.文件数据的收集需要使用formdata
        // 2.收集所有表单元素的数据: new FormData(form),还可以只收集文件数据: formdata.append(key,File对象)
        let myfile = heroImg.files[0]
        if (!myfile) return
    
        let formdata = new FormData()
        formdata.append('file_data', myfile)
        // 发起axios请求
        axios({
          method: 'post',
          url: 'http://127.0.0.1:3001/uploadFile',
          data: formdata
        }).then(res => {
          // console.log(res)
          if (res.data.code == 200) {
            alert(res.data.msg)
            // res.data.src:文件上传成功之后,在服务器端的存储路径,我们就是将这个路径更新到用户信息
            // console.log(res.data.src)
    
            // 二:接下来要实现用户头像的s编辑
          }
        })
      })
    

实现用户头像的编辑

看接口文档

编辑操作有一个特点:你传递什么参数,就进行什么编辑

重点说明:编辑操作一定要考虑是否有条件,因为如果没有传递条件,就会更新所有数据,所以我们的编辑操作必须传递id

意味着我们更新用户头像最少需要传递两个参数

  • id:当前英雄数据的id,我们可以在按钮中添加自定义属性的存储,单击按钮之后,获取id,将其存储到一个变量中,供请求来使用
  • img:来自于文件上传成功之后,服务器所返回的路径

id的处理

  • 添加列表中的”上传文件“按钮的自定义属性存在

    <button type="button" class="btn btn-info btnEdit" data-id='${value.id}'>
        上传头像
    </button>
    
  • 单击列表中的”上传文件“按钮,获取自定义属性,并转存到一个公共变量中

    // 打开上传文件模态框:只是打开上传文件的模态框,并没有做上传文件的操作,:动态生成的元素的事件绑定需要使用事件委托
      tbody.addEventListener('click', function(e) {
        if (e.target.classList.contains('btnupload')) {
          $('#uploadImgModal').modal('show')
          editId = e.target.dataset.id
        }
      })
    
  • 在编辑用户信息的时候,使用这个公共变量

    axios
        .post(
        'http://127.0.0.1:3001/updateHero',
        `id=${editId}&img=${res.data.src}`
    )
        .then(result => {
        // console.log(result)
        if (result.data.code == 200) {
            alert(result.data.msg)
            $('#uploadImgModal').modal('hide')
            init()
        }
    })
    

完整代码

// 实现文件上传
  btnHeroEdit.addEventListener('click', function() {
    // 一:实现文件上传
    // 1.文件数据的收集需要使用formdata
    // 2.收集所有表单元素的数据: new FormData(form),还可以只收集文件数据: formdata.append(key,File对象)
    let myfile = heroImg.files[0]
    if (!myfile) return

    let formdata = new FormData()
    formdata.append('file_data', myfile)
    // 发起axios请求
    axios({
      method: 'post',
      url: 'http://127.0.0.1:3001/uploadFile',
      data: formdata
    }).then(res => {
      // console.log(res)
      if (res.data.code == 200) {
        alert(res.data.msg)
        // res.data.src:文件上传成功之后,在服务器端的存储路径,我们就是将这个路径更新到用户信息
        // console.log(res.data.src)

        // 二:接下来要实现用户头像的s编辑
        axios
          .post(
            'http://127.0.0.1:3001/updateHero',
            `id=${editId}&img=${res.data.src}`
          )
          .then(result => {
            // console.log(result)
            if (result.data.code == 200) {
              alert(result.data.msg)
              $('#uploadImgModal').modal('hide')
              init()
            }
          })
      }
    })
  })