最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React 实现图片上传和展示功能

    正文概述 掘金(前端小黑)   2021-03-31   1723

    基本介绍 ?

    • 最近完成了产品提出的一个类似微信发图文朋友圈的需求(以下实现均基于 React + mobx 项目):
      • 1⃣️ 通过➕号按钮选择系统图片,最多可选择9张图,选择的图片以九宫格形式展示
      • 2⃣️ 选择图片后开始上传,图片大小限制为 20 MB,超过限制不上传且不展示
      • 3⃣️ 展示图片上传过程中的 loading 状态
      • 4⃣️ 图片上传失败可点重试按钮重新上传
      • 5⃣️ 可以删除选中的图片(若上传中删除前还需中断 xhr 请求)
      • 6⃣️ 发布后的图片内容按照一定规则展示(单图片、四宫格和九宫格)
    • 历尽千辛万苦终于实现了以上的功能,具体效果如下:
      • 上传图片页面:
      React 实现图片上传和展示功能
      • 展示页面(单图,按照单图规则展示):
      React 实现图片上传和展示功能
      • 展示页面(四图,四宫格):
      React 实现图片上传和展示功能
      • 展示页面(多图,九宫格):
      React 实现图片上传和展示功能
    • 该需求涉及到许多零散的知识点,遂以此文做总结记录,下面将介绍思路和具体的实现代码。

    思路分析 ?

    选择图片

    • 选择图片可以用设置 type 属性为 file 值的 input 标签:
    <input type="file" accept="image/gif,image/jpeg,image/jpg,image/png" multiple />
    
    • 通过设置其 multiple 属性和 accept 属性可以使得 input 标签支持多选和仅支持选择 gifjpg/jpegpng 类型的文件。

    React 实现图片上传和展示功能

    • 当点击标签时,则可以从文件系统中选择照片。我们的需求是提供一个➕号按钮作为选择图片的入口,这里可以使用 ref 获取该 input 元素,当点击➕号按钮时触发 input 的点击事件,即可以调用系统的相册进行图片选取。

    限制图片大小和数量、预览本地图片

    • input 元素的 change 事件被触发时,可以通过 input.files 获取到当前选中文件的 FileList 类数组对象,当选择两张图片后,打印 FileList 对象: React 实现图片上传和展示功能
    • 可以看到每个 File 对象都有 size 字段,可以用来判断图片大小(字节)是否超过限制(20MB20 * 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 可作为图片的源
      <img src={localUrl} alt='' />
      
      // 无需使用时释放内存
      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 状态,添加的图片可以被删除,即效果如下: React 实现图片上传和展示功能

    • 首先是 UploadImage 组件,代码如下: React 实现图片上传和展示功能 React 实现图片上传和展示功能

    • UploadImage 组件中使用了 ImageItem 子组件,封装了上传、删除、重试逻辑,相关代码如下: React 实现图片上传和展示功能

    • 样式文件代码如下: React 实现图片上传和展示功能

    • 可以看到,在使用 UploadImage 组件时需要传入 imageList 和及其更新方法 updateImageList。接下来我们看使用 updateImageList 组件的最外层组件 PostEditorView 的相关代码:

      React 实现图片上传和展示功能

    • 上面的代码可以看到,可以写一些自定义 hooks 来减小 PostEditorView 组件的大小:

      • useConfirmModal 封装提交内容时的弹框逻辑
      • useAlertModal 封装图片上传失败时的弹框逻辑
      • useUploadInput 封装选择图片相关逻辑
    • 至此,上传图片页面相关组件的代码均已展示完成,建议结合思路阅读相关代码,仅提供思路,部分无关代码已删除。

    展示图片页面组件

    • 这部分将实现内容页的展示图片组件。BlogImageList 组件相关代码如下: React 实现图片上传和展示功能

    • 样式文件代码如下: React 实现图片上传和展示功能

    • 在展示页面,只需要将带图片id、原始宽高的图片列表传给组件即可。

    • PS:单张图使用微信朋友圈图片的显示规则,如下图所示,假设图片宽高比 X,当图片 1:1 时显示的尺寸为 Y * Y(在项目中 Y = 180,L = 4):

      React 实现图片上传和展示功能

    总结 ?

    • 本文主要整理了在 React 项目实现图片上传和展示功能的相关思路和代码,涉及到使用 input[type=file] 标签来唤起系统选择图片功能,使用 URL.createObjectURL() 对 File 对象进行处理实现本地图片预览,以及使用 xhr 实现无刷新图片上传等知识点。

    参考资料

    1. 前端图片上传那些事儿
    2. 在web应用程序中使用文件
    3. MDN - URL.createObjectURL()
    4. 微信朋友圈图片的显示规则

    起源地下载网 » React 实现图片上传和展示功能

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    有没有源代码呀大神
    回复(0)

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元