当前位置:   article > 正文

antd踩坑记录之upload上传_为何 filelist 受控时,上传不在列表中的文件不会触发 onchange 后续的 status

为何 filelist 受控时,上传不在列表中的文件不会触发 onchange 后续的 status 更

代码

  • 页面展示代码
<Modal
  visible={isShowUploadModal} //弹框是否显示
  onOk={this.handleCloseModel} // 点击确定时的操作
  onCancel={this.handleCloseModel} //点击取消时的操作
  title="文件上传"
  // 关闭时销毁子元素,这个很有用,相当于关闭的时候结束了组件的生命周期
  destroyOnClose={true}
>
  <Upload
    ref={this.modalRef} // 用到ref实现后面的弹框颜色控制
    action={apis.DeviceManagement} // 上传的地址
    headers={
      { Authorization: token } // 可以在header里加上token
    }
    maxCount={1} // 最大上传数量,控制为1
    accept=".xls, .xlsx" //upload文件接收什么样的文件
    beforeUpload={this.handlerBeforeUpload} // 上传前的操作记录
    onChange={this.statusChange} //上传后的操作记录
  >
    <Button type="primary">
      点击上传
    </Button>
  </Upload>
</Modal>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 事件处理代码
 // 文件上传的拦截
  handlerBeforeUpload = (file, fileList) => {
    const { size } = file
    if (size / 1024 / 1024 > 10) {
      message.error("文件大小不能超过10兆")
      return Upload.LIST_IGNORE
    }
    this.setState({
      uploadLoading: true
    })
    return true
  }
//onChange上传文件状态变化,有三个状态status:uploading done error。
//beforeUpload拦截的文件没有这些status
// 所以在onChange中将拦截的文件进行处理,一般来说,上传的文件要么走到error,
//要么走到done,进入error状态,代表接口报错了。走到done状态代表了上传成功状态。
 statusChange = (res) => {
   const { file, fileList } = res
   if (file.status == 'error') {
     message.error(file?.response?.msg||"文件上传失败,请检查一下数据是否有错")
   }
   if (file.status == 'done') {
      // 上传成功后重新获取数据
     if (file.response.code === 100) {
       // 通过ref将upload组件获取到后,调用上传失败的函数,实现在已经done后还能触
       //发向error状态时的字体颜色为红色状态
       this.modalRef.current.onError("文件上传失败", file.response, file)
     }
     if (file.response.code === 200) {
       message.success(file.response?.msg || "文件上传成功")
       // 上传成功后重新获取数据
       // this.getDeviceList()
     }
   }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

问题

  • 知识点
    onChange上传文件状态变化,有三个status:uploading, done ,error。
    beforeUpload拦截的文件是没有这些status的,所以在onChange中将拦截的文件进行处理,一般来说,上传的文件要么走到error,要么走到done,进入error状态,代表接口报错了。走到done状态代表了上传成功状态。
  • 问题
    因为上传的是excel文件,用后端对接接口返回的状态码来判断是否上传成功,还有显示后端的提示代码。所以这个时候已经走到done了,能拿到了状态和后端返回的response。但是后面遇到的问题是要在done这个状态里面判断是否上传成功,没有成功就让上传的文件变为红色,类似于下图
    在这里插入图片描述
    想到的解决办法就是
  • 1,要么利用变量控制css属性来实现
    实现起来有些问题,虽然可以通过浏览器元素审查来找到upload对应的类名进行修改。但是这样写的话可能就会通过操作dom元素来实现style的添加或删除颜色,与react的虚拟dom设计不符合,所以放弃
  • 2,通过upload自己来触发让他变红的事件(onError)
    react的ref属性可以获取到想要获取的元素。通过ref拿到后upload的属性后进行Onerror的调用this.modalRef.current.onError("文件上传失败", file.response, file)file.response 就是后台返回的数据, file是上传的文件。

遇到的坑

  • 场景
    因为upload嵌套在modal弹框里面,所以在点击弹框关闭时要将upload里面上传的文件销毁,或者说是清空upload中的fileList
  • 问题
    将fileList变为受控组件后,onChange事件拿到的状态一直是uploading
 <Upload
   ref={this.modalRef}
   action={apis.DeviceManagement}
   headers={
     { Authorization: Token.token }
   }
   fileList={fileList} // 将fileList变为受控组件
   maxCount={1}
   accept=".xls, .xlsx"
   beforeUpload={this.handlerBeforeUpload}
   onChange={this.statusChange}
 >
 </Upload>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

查阅了一下antd官网
为何 fileList 受控时,上传不在列表中的文件不会触发 onChange 后续的 status 更新 事件?
onChange 事件仅会作用于在列表中的文件,因而 fileList 不存在对应文件时后续事件 会被忽略

  • 解决方案
    最简方案,那么就在fileList不写在upload中,还是非受控的。modal关闭时销毁其子组件,刚好modal进行过封装destroyOnClose={true},当弹框关闭时可以销毁组件。
    destroyOnClose关闭时销毁 Modal 里的子元素
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/339061
推荐阅读
相关标签
  

闽ICP备14008679号