react拖拽組件
最近忙着公司后台系統開發,因為需求用到了拖拽.給大家安利幾個好用的拖拽組件!
1.第一個拖拽組件 antd的Tree組件
這個拖拽組件經常用於層級關系的拖拽組件 可以
動態的增刪改 (排序,添加子層級~父層級,修改等).

import React, { useEffect, useState } from "react" import { Tree, message } from 'antd'; //導入antd 的Tree組件 export default function App() { const [data, setData] = useState([]) useEffect(() => { if (data.length === 0) { //初始化數據 setData([{ title: "組1", key: 1 }, { title: "組2", key: 2, children: [{ title: "子組1", key: 6 }, { title: "子組2", key: 7 }, { title: "子組3", key: 9 }] }, { title: "組3", key: 3 }, { title: "組4", key: 4 }]) } }, [data]) //完成拖拽 const onDrop = info => { /** * 這里是判斷 拖拽之后的動作是否允許存在跨級拖拽交換位置等等... * 若需要判斷可以取消注釋 */ // let nodePosArr = info.node.pos.split('-') // let dropPosArr = info.dragNode.pos.split('-') // if (dropPosArr.length === nodePosArr.length && nodePosArr[1] !== dropPosArr[1]) return message.error("不可拖入其他類別") // if (nodePosArr.length !== dropPosArr.length) return message.error("列表禁止跨級拖拽") // if (!info.dropToGap) return message.error("同級列表只能互換順序") const dropKey = info.node.props.eventKey; const dragKey = info.dragNode.props.eventKey; const dropPos = info.node.props.pos.split('-'); const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]); const loop = (data, key, callback) => { for (let i = 0; i < data.length; i++) { if (data[i].key === key) { return callback(data[i], i, data); } if (data[i].children) { loop(data[i].children, key, callback); } } }; const changeData = [...data]; // Find dragObject let dragObj; loop(changeData, dragKey, (item, index, arr) => { arr.splice(index, 1); dragObj = item; }); if (!info.dropToGap) { // Drop on the content loop(data, dropKey, item => { item.children = item.children || []; // where to insert 示例添加到尾部,可以是隨意位置 item.children.push(dragObj); }); } else if ( (info.node.props.children || []).length > 0 && // Has children info.node.props.expanded && // Is expanded dropPosition === 1 // On the bottom gap ) { loop(data, dropKey, item => { item.children = item.children || []; // where to insert 示例添加到頭部,可以是隨意位置 item.children.unshift(dragObj); }); } else { let ar; let i; loop(data, dropKey, (item, index, arr) => { ar = arr; i = index; }); if (dropPosition === -1) { ar.splice(i, 0, dragObj); } else { ar.splice(i + 1, 0, dragObj); } } //changeData就是拖拽結束后改變的數據格式, 需要在這里重新賦值 即可顯示最新拖拽之后的結果 setData(changeData) }; /** * * @param {Array} selectedKeys 選中的key 數組存放,單多選 * @param {Node} e 被選擇中的node信息,可以拿到 數據源, 層級關系等... */ //完成選擇 const onSelect = (selectedKeys, e) => { console.log(selectedKeys, e); } return <> <Tree draggable //是否可以拖拽 blockNode //是否節點占據一行 showLine // 是否展示連接線 treeData={data} //數據源 格式 Array 每項的數據格式Object { key:..., title:...,... } onDrop={onDrop} //拖拽結束后觸發的回調函數 onSelect={onSelect} // 選中某一級的回調函數 /> </> }
2. 第二個拖放組件 react-beautiful-dnd
這個拖拽組件用於列表拖拽,
只可以水平,垂直拖拽.拖拽的UI非常不錯, 可以動態增刪列表

import React, { useEffect, useState } from "react" import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; //每一項的樣式 const getItemStyle = () => ({ background: "white", height: 50, border: "1px solid red", width: "100%", margin: "0 0 20px 0" }) // 重新記錄數組順序 const reorder = (list, startIndex, endIndex) => { const result = Array.from(list); //刪除並記錄 刪除元素 const [removed] = result.splice(startIndex, 1); //將原來的元素添加進數組 result.splice(endIndex, 0, removed); return result; }; export default function App() { const [data, setData] = useState([]) useEffect(() => { if (data.length === 0) { //初始化數據 const newData = Array.from({ length: 5 }, (item, index) => ({ key: "key" + index, content: "item" + index })) setData(newData) } }, [data]) //拖拽結束 const onDragEnd = (result) => { if (!result.destination) { return; } //獲取拖拽后的數據 重新賦值 const newData = reorder(data, result.source.index, result.destination.index) setData(newData) } return <DragDropContext onDragEnd={onDragEnd}> {/* direction代表拖拽方向 默認垂直方向 水平方向:horizontal */} <Droppable droppableId="droppable"> {(provided, snapshot) => ( //這里是拖拽容器 在這里設置容器的寬高等等... <div {...provided.droppableProps} ref={provided.innerRef} style={{ width: 800, padding: 10 }} > {/* 這里放置所需要拖拽的組件,必須要被 Draggable 包裹 */} { data.map((item, index) => ( <Draggable index={index} key={item.key} draggableId={item.key} > {(provided, snapshot) => ( //在這里寫你的拖拽組件的樣式 dom 等等... <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} style={{ ...getItemStyle(), ...provided.draggableProps.style }} > {item.content} </div> )} </Draggable> )) } {/* 這個不能少 */} {provided.placeholder} </div> )} </Droppable> </DragDropContext> }
3.第三個拖拽組件 react-draggable-tags
一個輕量級的拖拽排序組件。該組件封裝了一系列拖拽功能,可以靈活使用,也未提供任何樣式,完全由你來控制(不一定是“tag”,你可以放入任意組件來拖拽排序)。支持移動端。

import React, { useEffect, useState } from "react"; import { DraggableArea } from 'react-draggable-tags'; export default function App() { const [data, setData] = useState([]) useEffect(() => { if (data.length === 0) { setData([ { id: 1, content: 'apple' }, { id: 2, content: 'olive' }, { id: 3, content: 'banana' }, { id: 4, content: 'lemon' }, { id: 5, content: 'orange' }, { id: 6, content: 'grape' }, { id: 7, content: 'strawberry' }, { id: 8, content: 'cherry' }, { id: 9, content: 'peach' } ]) } }, [data]) //拖拽結束后觸發的函數,返回已經改變的data const onChange = (tags) => { console.log(tags); } //渲染每項 const itemRender = ({ tag, index }) => { return <div className="tag"> {tag.content} </div> } return <div className="Simple"> <DraggableArea tags={data} render={itemRender} onChange={onChange} /> </div> }