antd踩坑记录之upload上传

代码

  • 页面展示代码
<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>
  • 事件处理代码
 // 文件上传的拦截
  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()
     }
   }
 }

问题

  • 知识点
    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>

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

  • 解决方案
    最简方案,那么就在fileList不写在upload中,还是非受控的。modal关闭时销毁其子组件,刚好modal进行过封装destroyOnClose={true},当弹框关闭时可以销毁组件。
    destroyOnClose关闭时销毁 Modal 里的子元素

猜你喜欢

转载自blog.csdn.net/weixin_45701199/article/details/125988876