产品提出期望:上传后的多张图片,希望能够拖动图片调整图片顺序。
技术选型:react-sortable-hoc。(为什么选择这个?因为之前使用过,第一时间想到的。也可以用其他拖拽库)。
拖拽图片的代码:
import React, { CSSProperties, memo, useState } from 'react';
import { SortableContainer, SortableElement, SortEnd } from 'react-sortable-hoc';
import { UploadFile } from 'antd/es/upload/interface';
import { UploadChangeParam } from 'antd/lib/upload';
import UploadList from 'antd/es/upload/UploadList';
import { Modal, Upload } from 'antd';
import arrayMove from 'array-move';
import styles from './picturesGrid.less';
const SortableItem = SortableElement((params: any) => {
return (
<div className={styles.itemStyle}>
<UploadList
locale={{ previewFile: '预览图片', removeFile: '删除图片' }}
showDownloadIcon={false}
listType={params.props.listType}
onPreview={params.onPreview}
onRemove={params.onRemove}
items={[params.item]}
/>
</div>
);
});
const SortableList = SortableContainer((params: any) => {
return (
<div className={styles.listStyle}>
{params.items.map((item: any, index: any) => (
<SortableItem
key={`${item.uid}`}
index={index}
item={item}
props={params.props}
onPreview={params.onPreview}
onRemove={params.onRemove}
/>
))}
//这个是上传组件,设置了最大上传限制,当上传数量达到上限后,设置隐藏。
<div
className={styles.uploadBox}
style={!params.props.children ? { display: 'none' } : { display: 'block' }}
>
<Upload {...params.props} showUploadList={false} onChange={params.onChange}>
{params.props.children}
</Upload>
</div>
</div>
);
});
const PicturesGrid: React.FC<any> = memo(({ onChange: onFileChange, ...props }) => {
const fileList = props.fileList || [];
const onSortEnd = ({ oldIndex, newIndex }: SortEnd) => {
if (oldIndex !== newIndex) {
let newData: any = arrayMove([].concat(fileList), oldIndex, newIndex).filter(el => !!el);
newData = newData.map((item: any, index: number) => ({ ...item, index }));
onFileChange({ fileList: newData });
}
};
const onChange = ({ fileList: newFileList }: UploadChangeParam) => {
onFileChange({ fileList: newFileList });
};
const onRemove = (file: UploadFile) => {
const newFileList = fileList.filter((item: any) => item.uid !== file.uid);
onFileChange({ fileList: newFileList });
};
return (
<SortableList
//这个通过查阅 当移动 1 之后再触发排序事件,默认是0,会导致无法触发图片的预览和删除事件
distance={1}
items={fileList}
onSortEnd={onSortEnd}
axis="xy"
helperClass="SortableHelper"
props={props}
onChange={onChange}
onRemove={onRemove}
//这个是图片预览,按照你之前的逻辑就可。不需做修改
onPreview={props.onPreview}
/>
);
});
export default PicturesGrid;
调用的父组件代码:
const [fileListForm, setfileListForm] = useState([]);
<PicturesGrid
// 这个地址可以替换你们的文件服务地址
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
multiple={true}
listType="picture-card"
// 这是图片列表,格式就是上传图片后的文件格式
fileList={fileListForm}
//这个是你图片上传的限定格式
accept={uploadTypes}
onChange={handleChange}
// 这两个函数一个是预览一个是上传之前的回调,直接用你之前的函数即可
//onPreview={handlePreview}
//beforeUpload={beforeUpload}
>
{fileListForm.length >= 7 ? null : uploadButton}
</PicturesGrid>
//这个就是一个上传组件中间的样式。
const uploadButton = (
<div>
<div style={{ fontSize: 12 }}>图片</div>
</div>
);
//handlechange 函数
const handleChange = ({ fileList }: UploadChangeParam<any>) => {
// 这个处理是上传图片时候的处理。
fileList = fileList.map((file: any) => {
if (file.response && file.response.code === 200) {
file.url = file.response.data.msg;
file.thumbUrl = file.response.data.msg;
}
return file;
});
if (fileList.length > 7) {
return message.info('图片最多上传七张');
}
//现在的fileList就是调整后的顺序。然后比就可以set了。
setfileListForm(fileList )
};
遇到的问题:
当第一次直接上传图片后,不知什么原因,鼠标移动到组件上方,出现预览和删除,删除可以点击,但是预览不可以,只能曲线救国:
解决:当在f12中观察dom。发现添加了css样式,将图标变透明了。所以我是将样式再强制改了回来:
.ant-upload-list-item-actions {
a {
pointer-events: painted !important;
opacity: 1 !important;
}
}