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,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,item => {
item.children = item.children || [];
// where to insert 示例添加到头部,可以是随意位置
item.children.unshift(dragObj);
});
} else {
let ar;
let i;
loop(data,arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i,dragObj);
} else {
ar.splice(i + 1,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,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,removed);
return result;
};
export default function App() {
const [data,setData] = useState([])
useEffect(() => {
if (data.length === 0) {
//初始化数据
const newData = Array.from({ length: 5 },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
import React,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>
}