![在这里插入图片描述](https://img-blog.csdnimg.cn/f053ea6f2bdb4077ad4a051c4f8c355b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAd2FpbGx5ZXI=,size_20,color_FFFFFF,t_70,g_se,x_16)
html 拖拽排序
import React, { useState, useRef } from 'react';
import { cloneDeep } from 'lodash';
import styles from './index.less';
const defaultList = [
{
id: 1,
name: '11',
},
{
id: 2,
name: '22',
},
];
export default ({ children = '', arr = [] }) => {
const [list, setList] = useState([...defaultList]);
const startRef = useRef(null);
const changePosition = (dragIndex, hoverIndex) => {
const data = cloneDeep(list);
const temp = data[dragIndex];
data[dragIndex] = data[hoverIndex];
data[hoverIndex] = temp;
setList(data);
};
const onDragStart = index => {
startRef.current = index;
};
const onDragEnd = (e, index) => {
e.preventDefault();
};
const onDragOver = (e, index) => {
e.preventDefault();
};
const onDragEnter = (e, hoverIndex) => {
e.preventDefault();
if (startRef.current === hoverIndex) {
return;
}
startRef.current = hoverIndex;
changePosition(startRef.current, hoverIndex);
};
return (
<div className={styles.list_container}>
{list.map((item, index) => {
return (
<div
className={styles.list_item}
draggable
key={item?.id}
onDragStart={$event => onDragStart(index)}
onDragEnd={$event => onDragEnd($event, index)}
onDragEnter={$event => onDragEnter($event, index)}
onDragOver={$event => onDragOver($event, index)}
>
{item.name}
{}
</div>
);
})}
</div>
);
};
拖拽组件封装
import React, { useRef } from 'react';
import { useDrop, useDrag } from 'react-dnd';
import styles from './index.less';
export default ({ id = '', index = '', changePosition = () => {}, className = {}, children, rowKey = '' }) => {
const ref = useRef(null);
const [, drop] = useDrop({
accept: 'DragDropBox',
hover: (item, monitor) => {
if (!ref.current) return;
const dragIndex = item.index;
const hoverIndex = index;
if (dragIndex === hoverIndex) return;
changePosition(dragIndex, hoverIndex);
item.index = hoverIndex;
},
});
const [{ isDragging }, drag] = useDrag({
item: {
type: 'DragDropBox',
id,
index,
},
collect: monitor => ({
isDragging: monitor.isDragging(),
}),
});
return (
<div ref={drag(drop(ref))} style={{ opacity: isDragging ? 0.5 : 1 }} className={className.dragBox}>
<span key={rowKey} className={styles.reviewer}>
{children}
</span>
</div>
);
};
使用组件
import React from 'react';
import { DndProvider } from 'react-dnd';
import { useSelector } from 'umi';
import { cloneDeep } from 'lodash';
import HTML5Backend from 'react-dnd-html5-backend';
import ReactDndDragSort from '@/components/ReactDndDragSort';
import styles from './index.less';
export default ({ currentModel, dispatch }) => {
const { reviewerList = [] } = useSelector(state => state[currentModel]);
const changePosition = (dragIndex, hoverIndex) => {
const data = cloneDeep(reviewerList);
const temp = data[dragIndex];
data[dragIndex] = data[hoverIndex];
data[hoverIndex] = temp;
dispatch({
type: `${currentModel}/overrideStateProps`,
payload: {
reviewerList: data,
},
});
};
return (
<>
<div className={styles.reviewerContainer}>
<DndProvider backend={HTML5Backend}>
{reviewerList?.length ? (
<div style={{ display: 'flex' }}>
{reviewerList.map((item, index) => {
return (
<ReactDndDragSort
rowKey={item?.id}
index={index}
id={item?.id}
changePosition={changePosition}
>
<span key={item?.id} className={styles.reviewer}>
<div className={styles.reviewerImg}>
<span
className="saas saas-failure1"
onClick={() => {
const listFilter = reviewerList.filter(
(_, itemIndex) => itemIndex !== index,
);
dispatch({
type: `${currentModel}/overrideStateProps`,
payload: {
reviewerList: listFilter,
},
});
}}
/>
</div>
<div className={styles.reviewerTxt}>{item.name}</div>
</span>
</ReactDndDragSort>
);
})}
</div>
) : null}
</DndProvider>
</div>
</>
);
};
ts 版本
import React, { useRef } from "react";
import { useDrop, useDrag } from "react-dnd";
import "./index.less";
export default (props: any) => {
const {
id = "",
index = "",
changePosition = () => {},
className = "",
children,
rowKey = "",
} = props;
const ref: any = useRef(null);
const [, drop] = useDrop({
accept: "DragDropBox",
hover: (item: any, monitor: any) => {
if (!ref.current) return;
const dragIndex = item.index;
const hoverIndex = index;
if (dragIndex === hoverIndex) return;
changePosition(dragIndex, hoverIndex);
item.index = hoverIndex;
},
});
const [{ isDragging }, drag] = useDrag(() => ({
type: "DragDropBox",
item: { id, type: "DragDropBox", index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
}));
const changeRef = drag(drop(ref));
return (
<div
ref={changeRef}
style={{ opacity: isDragging ? 0.5 : 1 }}
className="dragBox"
>
<span key={rowKey} className={className}>
{children}
</span>
</div>
);
};
ts使用
import React, { useState } from "react";
import { DndProvider } from "react-dnd";
import { useSelector } from "react-redux";
import { cloneDeep } from "lodash";
import { HTML5Backend } from "react-dnd-html5-backend";
import ReactDndDragSort from "@/components/ReactDndDragSort";
import "./index.less";
console.log("HTML5Backend", HTML5Backend);
export default () => {
const dList = [
{
id: 99,
name: "组1",
},
{
id: 22,
name: "组2",
},
];
const [reviewerList, setReviewerList] = useState(dList);
const changePosition = (dragIndex: any, hoverIndex: any) => {
const data = cloneDeep(reviewerList);
const temp = data[dragIndex];
data[dragIndex] = data[hoverIndex];
data[hoverIndex] = temp;
console.log("交换完成---", data);
setReviewerList(data);
};
return (
<>
<div className="reviewerContainer">
<DndProvider backend={HTML5Backend}>
{reviewerList?.length ? (
<div>
{reviewerList.map((item: any, index: any) => {
return (
<ReactDndDragSort
rowKey={item?.id}
index={index}
id={item?.id}
changePosition={changePosition}
>
<div key={item?.id} className="reviewer">
<div className="reviewerTxt">{item.name}</div>
</div>
</ReactDndDragSort>
);
})}
</div>
) : null}
</DndProvider>
</div>
</>
);
};