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 | 读完的文件,格式为对应的调用函数 |
然后这是读取文件的方法:
方法 | 参数 | 描述 |
---|---|---|
abort | none | 中断读取
\\newline
调用后 FileReader.readyState 会变成 2 ,即 DONE |
readAsArrayBuffer | file or blob | 将文件读取为 ArrayBuffer,适合处理图片这样的文件
\\newline
这是一个新一点的 API,所以不是所有的浏览器都会支持,向下兼容的 API 为 readAsBinaryString() |
readAsDataURL | file or blob | 将文件读取为 DataURL(base64 encoded string) |
readAsText | file 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--封装上传组件的主要内容,如果未能解决你的问题,请参考以下文章