react封装图片上传组件
支持表单受控和非受控使用,基于antd upload 进行的二次封装,
使用场景如下图:
1.组件文件夹
2. index.tsx贴代码
import React, { useEffect, useMemo, useState } from 'react';
import { ImageFilesWrapper } from './style';
import type { RcFile, UploadProps } from 'antd/es/upload';
import type { UploadFile } from 'antd/es/upload/interface';
import { message, Modal } from 'antd';
import icon from './img/uil_image_plus.svg';
import { uploadImageFileWithNoToken } from 'requests/fileUpload-requests';
import { addUriPrefixIfNeeded } from 'utils/requests/utils'; // 转化url
import { v4 } from 'uuid';
interface Iprops {
onChange?: (data) => void;
onRemove?: (data) => void;
maxCount?: number; //可上传的图片张数
value?: string[]; // 表单默认值
multiple?: boolean;
}
interface Iflie {
uid: string;
status: string;
url: string;
} //图片上传
export default function ImageUpload(props: Iprops) {
const { onChange, multiple, value, onRemove, maxCount } = props;
// 处理 表单传入的值
const defaultList = useMemo(() => {
if (value?.length) {
let list: Iflie[] = [];
value?.map(v => {
list.push({
uid: v4(),
status: 'done',
url: addUriPrefixIfNeeded(v),
});
});
return list;
}
}, [value]); const [fileList, setFileList] = useState<any>(defaultList || []); const [previewVisible, setPreviewVisible] = useState(false);
const [previewImage, setPreviewImage] = useState('');
const [previewTitle, setPreviewTitle] = useState(''); const handleCancel = () => setPreviewVisible(false);
const handleChange: UploadProps['onChange'] = async ({
fileList: newFileList,
}) => {
setFileList(newFileList || []);
let urlList: any = [];
newFileList?.map(v => {
if (v?.response?.fileId || v.url) {
urlList.push(v?.response?.fileId || v.url);
}
});
onChange?.(urlList);
}; const getBase64 = (file: RcFile): Promise<string> =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result as string);
reader.onerror = error => reject(error);
}); const handlePreview = async (file: UploadFile) => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj as RcFile);
}
setPreviewImage(file.url || (file.preview as string));
setPreviewVisible(true);
setPreviewTitle(
file.name || file.url!.substring(file.url!.lastIndexOf('/') + 1),
);
}; async function uploadHeadImg(info) {
try {
const res = await uploadImageFileWithNoToken(info.file);
if (res) {
message.info('上传成功');
info.onSuccess(res, info.file); // 上传成功触发
} else {
message.error('上传失败');
}
} catch (error) {
info.onError(error, undefined, info.file); // 上传失败触发
// @ts-ignore
message.error(error?.message || '上传失败');
console.error(error);
}
} return (
<>
<ImageFilesWrapper
listType="picture-card"
fileList={fileList}
onPreview={handlePreview}
multiple={multiple}
maxCount={maxCount}
accept=".png,.jpg,.jpeg"
beforeUpload={file => {
if (!['image/png', 'image/jpg', 'image/jpeg'].includes(file.type)) {
message.info('仅支持上传png/jpg/jpeg格式的图片');
}
return ['image/png', 'image/jpg', 'image/jpeg'].includes(file.type);
}}
onChange={handleChange}
onRemove={(data: any) => {
console.log(data, 'data,remove');
if (data?.disabled) {
return Promise.resolve(false);
} else {
return onRemove ? onRemove(data) : Promise.resolve(true);
}
}}
customRequest={uploadHeadImg}
>
{((maxCount && fileList?.length < maxCount) || !maxCount) && (
<div className="imgButton">
<img src={icon} alt="" />
<div>添加图片</div>
</div>
)}
</ImageFilesWrapper> <Modal
open={previewVisible}
title={previewTitle}
footer={null}
onCancel={handleCancel}
>
<img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal>
</>
);
}
3.样式代码
import { Upload } from 'antd';
import styled from 'styled-components/macro'; export const ImageFilesWrapper = styled(Upload)`
text-align: left;
.adm-image-uploader-cell {
width: 60px;
height: 60px;
line-height: 60px;
}
.adm-image-uploader {
}
.upload-finsh {
color: #0ebd73;
margin-right: 10px;
}
.imgButton {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
color: var(--primary-color);
img {
margin-right: 5px;
}
}
`;
4.页面表单使用
<Form.Item
label="人员头像"
name="headerImg"
rules={[
{
required: false,
},
]}
valuePropName="value"
trigger="onChange"
>
<ImageUpload maxCount={1} />
</Form.Item>
表单初始值赋:
initialValues={{
headerImg: infoToEdit?.avatarUrl ? [infoToEdit.avatarUrl] : undefined,
}}
react封装图片上传组件的更多相关文章
- 微信小程序简单封装图片上传组件
微信小程序简单封装图片上传组件 希望自己 "day day up" -----小陶 我从哪里来 在写小程序的时候需要上传图片,个人觉得官方提供的 Uploader 组件不是太好用, ...
- React后台管理手动封装图片上传组件
分为两个文件夹,index.js(逻辑文件) styled.js(样式文件) index.js文件,编写完成之后在对应的地方引入即可 import React from "react&quo ...
- 基于Node的React图片上传组件实现
写在前面 红旗不倒,誓把JavaScript进行到底!今天介绍我的开源项目 Royal 里的图片上传组件的前后端实现原理(React + Node),花了一些时间,希望对你有所帮助. 前端实现 遵循R ...
- 分享一个react 图片上传组件 支持OSS 七牛云
react-uplod-img 是一个基于 React antd组件的图片上传组件 支持oss qiniu等服务端自定义获取签名,批量上传, 预览, 删除, 排序等功能 需要 react 版本大于 v ...
- vue图片上传组件
前言:很多项目中都需要用到图片上传功能,而其多处使用的要求,为了避免重复造轮子,让我决定花费一些时间去深入了解,最终封装了一个vue的图片上传组件.现将总结再次,希望有帮助. Layout <d ...
- Jquery图片上传组件,支持多文件上传
Jquery图片上传组件,支持多文件上传http://www.jq22.com/jquery-info230jQuery File Upload 是一个Jquery图片上传组件,支持多文件上传.取消. ...
- H5拍照、选择图片上传组件核心
背景 前段时间项目重构,改成SSR的项目,但之前用的图片选择上传组件不支持SSR(server-side-render).遂进行了调研,发现很多的工具.但有的太大,有的使用麻烦,有的不满足使用需求.决 ...
- 图片上传组件webuploader
前端组件webuploader 当时也是搞了很久参考这种demo,但是没记.现在事后大致总结下.直接上大概代码(我使用asp.net MVC来做的): 执行顺序:(get)Record/Add——A ...
- vux-uploader 图片上传组件
1.网址:https://github.com/greedying/vux-uploader 2.安装 npm install vux-uploader --save npm install --sa ...
- 【antd Vue】封装upload图片上传组件(返回Base64)
最近需要把上传的图片信息存储到数据库,以base64的方式,需要重新封装一下antd的upload组件 1. 使用方法 引入组件然后配置一下即可使用,配置项包括 defaultImageList,需要 ...
随机推荐
- mybatis-plus主键生成策略(实体类配置,数据库插入数据自动生成id)
转载:MyBatisplus -- ActiveRecord(AR)_mybatisplus idtype.auto_憨憨浩浩的博客-CSDN博客 0.auto:自动增长(mysql,sql serv ...
- python peewee
from peewee import MySQLDatabase, Model from peewee import CharField, IntegerField, BooleanField # 引 ...
- css样式 div垂直水平居中对齐
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- sqlalchemy+pandas:错误 'OptionEngine' object has no attribute 'execute','str' object has no attribute '_execute_on_connection'
场景:使用 sqlalchemy+pandas 1. 'OptionEngine' object has no attribute 'execute' import pandas as pd fro ...
- CDO学习2 CDO 入门教程Tutorial
#20210117#注:如果需要用cdo对数据进行截取,可参考buguse的几篇博文: 如何利用CDO从数据集中提取数据 CDO条件性选择数据 - 云+社区 - 腾讯云 CDO转换数据集格式 - 云+ ...
- PMP项目启动会与开工会议
转载https://www.cnblogs.com/yanpeng1991/p/11391805.html 项目启动会(project initiating meeting)与项目开工会(kick-o ...
- JSP课设:学生选课系统(附源码+调试)
JSP学生选课管理系统学生选课管理系统功能概述(1)登录模块分为两种角色:学生角色.教师角色 (2)教师模块:选课管理功能为对课程信息(课程编号.名称.学分)进行添加.修改.删除操作:学生信息功能对学 ...
- mount无响应
mount -t xfs /dev/sdb /data 挂载不成功,且命令无任何回显. dmesg 查看到有报错 tailf /var/log/messages -n 100 systemctl da ...
- 暴雪、迪士尼大佬用什么画画?RayLink远控软件助力解锁远程创作
CG绘画从业者,如原画师.插画师.漫画家.设计师等,一定对数位板\数位屏不陌生,数位板\数位屏是完成CG绘画作品的重要绘图工具之一. 从画画小白到数字绘画大神,从0基础插画培训班学生到国际知名游戏.动 ...
- 第6课第4节_Binder系统_驱动情景分析_服务注册过程_分析
Service_manager.c 8074 2017/6/30 首先从应用程序分析(Android) binder_loop(bs, svcmgr_handler) { readbuf[0] = B ...