react--封装上传组件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react--封装上传组件相关的知识,希望对你有一定的参考价值。

参考技术A 我的项目中充斥着大量的视频、音频、和图片上传,像这种情况,将组建封装成一个,在使用时直接引入传入一些配置项,必定是高效的作业方式

新建一个upload文件

config来自于父组件,组件内部会根据config中的参数做一些处理

upBtnRef是antd的upload组件内的button组件,它的样式该起来麻烦的要死,因此我就直接将其visibility: "hidden",然后通过ref注册引用以达到触发上传的目的

fakeUpBtnRef是考虑到向父组件提供一个调用上传的接口,方便父组件自定义自己的样式,然后trigger到我们的上传组件。这将在useEffect中将组件的引用抛给父组件

isDefaut则用户进行上传前后的图片标识替换

actUrls则保持每一个组件激活的图片标识,这将对同一个组件中使用上传列表时有用

switch语句将根据不同上传类型设置可选择的文件类型

getBase64则将我们上传的图片转化为可展示的形式

onUploadChange则对我们的上传进度作监听,由于只有图片是可转化的,故对于音频和视频只需要切换其激活图标即可

getActImgUrl则用于图片列表时获取每一个组件的图片地址

最后页面结构如下

使用

React 中封装一个 FileReader 组件

React 中封装一个 FileReader 组件

最近有一个业务需求需要在页面内实现一个文件上传的功能,本来想找第三方库实现的,后来发现 HTML5 中新提供了一个 FileReader API 就能实现功能,因此就想着试试看自己写一个组件。

API 介绍

FileReader 有 6 个事件,以下是 MDN 中的描述:

事件描述
abort当文件读取放弃时调用,如调用 FileReader.abort()
error当文件读取出错时被调用
load当文件成功被读取时调用
loadend当文件读取结束时被调用
loadstart当文件读取开始时被调用
progress文件读取过程中随机调用 \\newline ProgressEvent 本身也有三个属性可以用来展示当前加载状态:lengthComputable, loaded, 和 total

几个事件的触发都可以通过 addEventListener 或者直接绑定对应事件完成触发:

addEventListener("progress", (event) => );

onprogress = (event) => ;

FileReader 中包含 3 个可读属性:

属性描述
FileReader.error一个用来描述文件读取时发生异常的 DOMException
FileReader.readyState表示文件读取的状态 \\newline 0 为实例已创建,但是还没开始读取 \\newline 1 为已经开始读取 \\newline 2 为操作已完成
FileReader.result读完的文件,格式为对应的调用函数

然后这是读取文件的方法:

方法参数描述
abortnone中断读取 \\newline 调用后 FileReader.readyState 会变成 2,即 DONE
readAsArrayBufferfile or blob将文件读取为 ArrayBuffer,适合处理图片这样的文件 \\newline 这是一个新一点的 API,所以不是所有的浏览器都会支持,向下兼容的 API 为 readAsBinaryString()
readAsDataURLfile or blob将文件读取为 DataURL(base64 encoded string)
readAsTextfile or blob, [encoding]将文件读取为文本,这个是最常操作的部分了,encoding 默认为 UTF-8

了解了基础的 API,那么就能封装一个简易的文件上传了

React 代码

这里分为两个组件写,组件 1 就是渲染部分:

添加了 onclick 事件去重新设置 event.target.value 之后,onChange 能够获取事件的变化,否则没有办法使用该组件重复上传文件。

import  useState  from "react";
import  readUploadFile  from "./fileReaderHelper";
import "./styles.css";

export default function App() 
  const [img, setImg] = useState("");

  const changeHandler = async (e) => 
    const res = await readUploadFile(e);
    console.log(res);
    setImg(res);
  ;

  return (
    <>
      <input
        type="file"
        onChange=changeHandler
        onClick=(e) => (e.target.value = null)
      />
      <p>Preview</p>
      <img src=img alt="sample img" />
    </>
  );

组件 2 为 UploadHelper:

做一个完整的组件其实需求部分挺多的,比如说如果需求包含上传图片、文档、视频、音频等,这里可能需要使用正则,根据上传的文件去调用对应的 API。

export const readUploadFile = (e) => 
  const reader = new FileReader();

  return new Promise((res, rej) => 
    reader.addEventListener("error", () => 
      reader.abort();
      rej(new Error("Problem reading file"));
    );

    reader.addEventListener("progress", (e) => 
      console.log(e.loaded + " has been transferred");
      console.log("file size: " + e.total);
      console.log(e.lengthComputable);
    );

    reader.addEventListener("load", () => 
      res(reader.result);
    );

    reader.addEventListener("loadstart", () => 
      // add some spinner
    );

    reader.addEventListener("loadend", () => 
      // remove spinner
    );

    reader.readAsDataURL(e.target.files[0]);
  );
;

整体代码来说比较简单,因为 FileReader 是异步函数,因此在返回的时候需要包装成一个 Promise 去实现。另外 FileReader 在 Web Workers 中也有实现,因此也可以实现非阻塞式上传。

效果图:

以上是关于react--封装上传组件的主要内容,如果未能解决你的问题,请参考以下文章

React 中封装一个 FileReader 组件

React 中封装一个 FileReader 组件

React 实现图片裁剪/上传/预览/下载/删除(主要是图片裁剪)

React -- 组件封装&props

react初探之父子组件通信封装公共组件

让开!!!谁也别拦着我封装React组件!