React 实现图片上传和展示功能 | 您所在的位置:网站首页 › 上传图片啊 › React 实现图片上传和展示功能 |
基本介绍 📝
最近完成了产品提出的一个类似微信发图文朋友圈的需求(以下实现均基于 React + mobx 项目):
1⃣️ 通过➕号按钮选择系统图片,最多可选择9张图,选择的图片以九宫格形式展示
2⃣️ 选择图片后开始上传,图片大小限制为 20 MB,超过限制不上传且不展示
3⃣️ 展示图片上传过程中的 loading 状态
4⃣️ 图片上传失败可点重试按钮重新上传
5⃣️ 可以删除选中的图片(若上传中删除前还需中断 xhr 请求)
6⃣️ 发布后的图片内容按照一定规则展示(单图片、四宫格和九宫格)
历尽千辛万苦终于实现了以上的功能,具体效果如下:
上传图片页面:
展示页面(单图,按照单图规则展示):
展示页面(四图,四宫格):
展示页面(多图,九宫格):
该需求涉及到许多零散的知识点,遂以此文做总结记录,下面将介绍思路和具体的实现代码。
思路分析 🤔
选择图片
选择图片可以用设置 type 属性为 file 值的 input 标签:
通过设置其 multiple 属性和 accept 属性可以使得 input 标签支持多选和仅支持选择 gif、jpg/jpeg 和 png 类型的文件。
当点击标签时,则可以从文件系统中选择照片。我们的需求是提供一个➕号按钮作为选择图片的入口,这里可以使用 ref 获取该 input 元素,当点击➕号按钮时触发 input 的点击事件,即可以调用系统的相册进行图片选取。
限制图片大小和数量、预览本地图片
当 input 元素的 change 事件被触发时,可以通过 input.files 获取到当前选中文件的 FileList 类数组对象,当选择两张图片后,打印 FileList 对象:
可以看到每个 File 对象都有 size 字段,可以用来判断图片大小(字节)是否超过限制(20MB 是20 * 1024 * 1024)。
区别于原生 APP,web 网页无法阻止用户选择超过 9 张图片,只能在代码中做限制,当总选择的图片超过 9 张则做超出数量提示和截断处理(取前 9 张图)。
由于可以获取到每张图片的 File 对象,则可以使用 URL.createObjectURL() 创建一个对象 URL,可以作为 img 标签的 src 值进行传入,则能实现本地图片的预览功能。
需要注意的是,当不再需要这些使用 URL.createObjectURL() 创建的 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放,让浏览器知道不用在内存中继续保留对这个文件的引用了(可设置图片的load事件处理器来释放对象URL,当图片加载完成之后对象URL就不再需要了)。
const localUrl = URL.createObjectURL(flieList[0])
// localUrl 可作为图片的源
// 无需使用时释放内存
window.URL.revokeObjectURL(localUrl);
上传图片和失败重试
通过前面的分析,我们可以获取到每张图片的 File 对象,我们就可以通过新建一个 FromData 对象,并将 File 对象添加到 FromData 对象中,使用 XMLHttpRequest 来处理无刷新上传图片。
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('file', fileData);
xhr.open('POST', UPLOAD_IMAGE_URL); // 需要后端提供上传 URL
xhr.send(formData);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// handle response
} else {
// handle error
}
}
}
上传失败时则重新执行以上上传逻辑。
图片展示
发布后的图片需要按照一定的规则展示:
单张图使用微信朋友圈图片的显示规则,需要获取图片原本的宽高,因此需要后端在上传图片完成后返回图片的原始宽高。
四张图时使用四宫格
其他数量的图片以九宫格形式展示
为了使得图片在保持其宽高比的同时填充 img 元素的整个内容框,我们通过可以设置 img 元素的 object-fit CSS 属性值为 cover 来实现。
下面将介绍整个图片上传和展示功能的具体实现代码。
具体实现 🧐
上传图片页面相关组件
这部分将实现创建页的上传图片组件,当添加图片张数少于9张时展示➕号按钮,图片添加后开始上传图片,图片上传过程中展示 loading 状态,添加的图片可以被删除,即效果如下: 首先是 UploadImage 组件,代码如下: UploadImage 组件中使用了 ImageItem 子组件,封装了上传、删除、重试逻辑,相关代码如下: 样式文件代码如下: 可以看到,在使用 UploadImage 组件时需要传入 imageList 和及其更新方法 updateImageList。接下来我们看使用 updateImageList 组件的最外层组件 PostEditorView 的相关代码: 上面的代码可以看到,可以写一些自定义 hooks 来减小 PostEditorView 组件的大小: useConfirmModal 封装提交内容时的弹框逻辑 useAlertModal 封装图片上传失败时的弹框逻辑 useUploadInput 封装选择图片相关逻辑至此,上传图片页面相关组件的代码均已展示完成,建议结合思路阅读相关代码,仅提供思路,部分无关代码已删除。 展示图片页面组件这部分将实现内容页的展示图片组件。BlogImageList 组件相关代码如下: 样式文件代码如下: 在展示页面,只需要将带图片id、原始宽高的图片列表传给组件即可。 PS:单张图使用微信朋友圈图片的显示规则,如下图所示,假设图片宽高比 X,当图片 1:1 时显示的尺寸为 Y * Y(在项目中 Y = 180,L = 4): 总结 👀 本文主要整理了在 React 项目实现图片上传和展示功能的相关思路和代码,涉及到使用 input[type=file] 标签来唤起系统选择图片功能,使用 URL.createObjectURL() 对 File 对象进行处理实现本地图片预览,以及使用 xhr 实现无刷新图片上传等知识点。以上内容如有遗漏错误,欢迎留言 ✍️指出,一起进步💪💪💪 如果觉得本文对你有帮助,🏀🏀留下你宝贵的 👍 参考资料 前端图片上传那些事儿 在web应用程序中使用文件 MDN - URL.createObjectURL() 微信朋友圈图片的显示规则 |
CopyRight 2018-2019 实验室设备网 版权所有 |