react + upload多个图片拖拽排序

1,670 阅读1分钟

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.效果展示(不会上传视频,展示截图)

1628057614(1).png

1628057645(1).png

好啦,大概就是这个意思,有疑问可以留言哦。 主要参考 github.com/dreamqyq/an…