1. 基于react + antd的upload组件,实现拖动图片排序的功能,首先安装插件
yarn add react-sortable-hoc
yarn add react-dnd
yarn add react-dnd-html5-backend
2. 封装拖拽组件
import React, { CSSProperties, memo, useState } from 'react';
import { arrayMove, SortableContainer, SortableElement, SortEnd } from 'react-sortable-hoc';
import './pictureGrid.css';
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 { Props, SortableItemParams, SortableListParams } from './types';
const itemStyle: CSSProperties = {
width: 104,
height: 104,
margin: 4,
cursor: 'grab'
};
const SortableItem = SortableElement((params: SortableItemParams) => (
<div style={itemStyle}>
<UploadList
locale={{ previewFile: '预览图片', removeFile: '删除图片' }}
showDownloadIcon={false}
listType={params.props.listType}
// onPreview={params.onPreview}
onRemove={params.onRemove}
items={[params.item]}
/>
</div>
));
const listStyle: CSSProperties = {
display: 'flex',
flexWrap: 'wrap',
maxWidth: '100%',
};
const SortableList = SortableContainer((params: SortableListParams) => {
return (
<div style={listStyle}>
{params.items.map((item, index) => (
<SortableItem
key={`${item.uid}`}
index={index}
item={item}
props={params.props}
// onPreview={params.onPreview}
onRemove={params.onRemove}
/>
))}
<Upload
{...params.props}
showUploadList={false}
onChange={params.onChange}
>
{params.props.children}
</Upload>
</div>
);
});
const PicturesGrid: React.FC<Props> = memo(({ onChange: onFileChange, ...props }) => {
const fileList = props.fileList || [];
const files = fileList[fileList.length-1]
const onSortEnd = ({ oldIndex, newIndex }: SortEnd) => {
//console.log(files,'顺序')
onFileChange({files, fileList: arrayMove(fileList, oldIndex, newIndex) },props.str);
};
const onChange = ({ file,fileList: newFileList }: UploadChangeParam) => {
//console.log(file,fileList,'filelits')
onFileChange({file, fileList: newFileList },props.str);
};
const onRemove = (file: UploadFile) => {
console.log('file', file)
console.log('fileList', fileList)
const newFileList = fileList.filter(
(item) => item.keyInd !== file.keyInd
);
onFileChange({ fileList: newFileList },props.str);
};
//预览部分
// const onPreview = async (file: UploadFile) => {
// await imagePreview(file, ({ image }) => {
// setPreviewImage(image);
// });
// };
return (
<>
<SortableList
// 当移动 1 之后再触发排序事件,默认是0,会导致无法触发图片的预览和删除事件
distance={1}
items={fileList}
onSortEnd={onSortEnd}
axis="xy"
helperClass="SortableHelper"
props={props}
onChange={onChange}
onRemove={onRemove}
//onPreview={onPreview}
/>
</>
);
});
export { PicturesGrid };
3.拖拽组件的方法定义及拖拽时的样式
import { UploadProps } from 'antd/lib/upload';
import { UploadChangeParam } from 'antd/lib/upload/interface';
import { ReactNode } from 'react';
export type Props = {
onChange: (params: { fileList: UploadFile[] }) => void;
children?: ReactNode;
} & UploadProps
type SortableParams = {
props: Omit<Props, 'onChange'>;
onPreview: (file: UploadFile) => void;
onRemove: (file: UploadFile) => void | boolean;
}
export type SortableItemParams = {
item: UploadFile;
} & SortableParams
export type SortableListParams = {
onChange: (info: UploadChangeParam) => void;
items: UploadFile[];
} & SortableParams
/* 拖动的时候的样式 */
.SortableHelper {
box-shadow: rgba(0, 0, 0, 0.075) 0 1px 6px, rgba(0, 0, 0, 0.075) 0 1px 4px;
background-color: lightgreen;
}
4.组件内使用
import React, { Component } from 'react';
import { Upload } from 'antd';
import { DndProvider, DragSource, DropTarget } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';
import { PicturesGrid } from './PicturesGrid';
<PicturesGrid //拖拽组件
name='culAucAuthPic'
action={SELF_PATH + '/api/uploadPic'}
listType="picture-card"
fileList={this.state[str]}
beforeUpload={type == 1 ? this.beforeUpload : this.beforeUploadVideo}
onChange={(e) => this.handleImgChange(e, str)}
onRemove={(e) => this.RemoveImg(e, str)}
str={str}
>
上传图片
</PicturesGrid>
5.效果展示(不会上传视频,展示截图)
好啦,大概就是这个意思,有疑问可以留言哦。 主要参考 github.com/dreamqyq/an…