react中實(shí)現(xiàn)拖拽排序react-dnd功能

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 => {
// console.log('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; // 將當(dāng)前當(dāng)前移動(dòng)到Box的index賦值給當(dāng)前拖動(dòng)的box,不然會(huì)出現(xiàn)兩個(gè)盒子瘋狂抖動(dòng)!
changePosition(startRef.current, hoverIndex);
// console.log('onDragEnd', 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}
{/* {children} */}
</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);
// 因?yàn)闆]有定義收集函數(shù),所以返回值數(shù)組第一項(xiàng)不要
const [, drop] = useDrop({
accept: 'DragDropBox', // 只對useDrag的type的值為DragDropBox時(shí)才做出反應(yīng)
hover: (item, monitor) => {
// 這里用節(jié)流可能會(huì)導(dǎo)致拖動(dòng)排序不靈敏
if (!ref.current) return;
const dragIndex = item.index;
const hoverIndex = index;
if (dragIndex === hoverIndex) return; // 如果回到自己的坑,那就什么都不做
changePosition(dragIndex, hoverIndex); // 調(diào)用傳入的方法完成交換
item.index = hoverIndex; // 將當(dāng)前當(dāng)前移動(dòng)到Box的index賦值給當(dāng)前拖動(dòng)的box,不然會(huì)出現(xiàn)兩個(gè)盒子瘋狂抖動(dòng)!
},
});
const [{ isDragging }, drag] = useDrag({
item: {
type: 'DragDropBox',
id,
index,
},
collect: monitor => ({
isDragging: monitor.isDragging(), // css樣式需要
}),
});
return (
// ref 這樣處理可以使得這個(gè)組件既可以被拖動(dòng)也可以接受拖動(dòng)
<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;
// setBoxList(data);
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";
// dnd拖拽排序
export default (props: any) => {
const {
id = "",
index = "",
changePosition = () => {},
className = "",
children,
rowKey = "",
} = props;
const ref: any = useRef(null);
// 因?yàn)闆]有定義收集函數(shù),所以返回值數(shù)組第一項(xiàng)不要
const [, drop] = useDrop({
accept: "DragDropBox", // 只對useDrag的type的值為DragDropBox時(shí)才做出反應(yīng)
hover: (item: any, monitor: any) => {
// 這里用節(jié)流可能會(huì)導(dǎo)致拖動(dòng)排序不靈敏
if (!ref.current) return;
const dragIndex = item.index;
const hoverIndex = index;
if (dragIndex === hoverIndex) return; // 如果回到自己的坑,那就什么都不做
changePosition(dragIndex, hoverIndex); // 調(diào)用傳入的方法完成交換
item.index = hoverIndex; // 將當(dāng)前當(dāng)前移動(dòng)到Box的index賦值給當(dāng)前拖動(dòng)的box,不然會(huì)出現(xiàn)兩個(gè)盒子瘋狂抖動(dòng)!
},
});
const [{ isDragging }, drag] = useDrag(() => ({
type: "DragDropBox",
item: { id, type: "DragDropBox", index },
collect: (monitor) => ({
isDragging: monitor.isDragging(), // css樣式需要
}),
}));
const changeRef = drag(drop(ref));
return (
// ref 這樣處理可以使得這個(gè)組件既可以被拖動(dòng)也可以接受拖動(dòng)
<div
//@ts-ignore
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";
//@ts-ignore
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>
</>
);
};
到此這篇關(guān)于react中實(shí)現(xiàn)拖拽排序react-dnd的文章就介紹到這了,更多相關(guān)react-dnd拖拽排序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- react-dnd實(shí)現(xiàn)任意拖動(dòng)與互換位置
- react-native 圓弧拖動(dòng)進(jìn)度條實(shí)現(xiàn)的示例代碼
- react項(xiàng)目中使用react-dnd實(shí)現(xiàn)列表的拖拽排序功能
- react?實(shí)現(xiàn)表格列表拖拽排序的示例
- React如何使用sortablejs實(shí)現(xiàn)拖拽排序
- React.js組件實(shí)現(xiàn)拖拽排序組件功能過程解析
- react.js組件實(shí)現(xiàn)拖拽復(fù)制和可排序的示例代碼
- react實(shí)現(xiàn)記錄拖動(dòng)排序
相關(guān)文章
react項(xiàng)目中express動(dòng)態(tài)路由未能匹配造成的404問題解決
本文主要介紹了react項(xiàng)目中express動(dòng)態(tài)路由未能匹配造成的404問題解決,解決了白屏的問題,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09
React使用Electron開發(fā)桌面端的詳細(xì)流程步驟
React是一個(gè)流行的JavaScript庫,用于構(gòu)建Web應(yīng)用程序,結(jié)合Electron框架,可以輕松地將React應(yīng)用程序打包為桌面應(yīng)用程序,本文詳細(xì)介紹了使用React和Electron開發(fā)桌面應(yīng)用程序的步驟,需要的朋友可以參考下2023-06-06
React中useState的使用方法及注意事項(xiàng)
useState通過在函數(shù)組件里調(diào)用它來給組件添加一些內(nèi)部state,下面這篇文章主要給大家介紹了關(guān)于React中useState的使用方法及注意事項(xiàng)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
React合成事件及Test Utilities在Facebook內(nèi)部進(jìn)行測試
這篇文章主要介紹了React合成事件及Test Utilities在Facebook內(nèi)部進(jìn)行測試,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
React 組件的狀態(tài)下移和內(nèi)容提升的操作方法
這篇文章主要介紹了React 組件的狀態(tài)下移和內(nèi)容提升,通過代碼講解了渲染性能的組件問題結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2022-11-11

