react dnd 实现拖拽功能,一个列表拖到另一个列表

 

1、拖拽组件封装

import React, { useState, useEffect } from 'react'

import { DndProvider, useDrop, useDrag } from 'react-dnd'

import HTML5Backend from 'react-dnd-html5-backend'

 

import { Row, Col, Card } from 'antd'

 

function DragPanel(props) {

 

const { dragItem, handleDrag, dragProps, firstCount } = props;

 

// 定义拖拽接收组件数据

const [dustbins, setDustbins] = useState([])

 

useEffect(() => {

if (dragProps) {

setDustbins(dragProps)

}

}, [dragProps])

 

function handleDrop(data) {

// console.log(data)

handleDrag(data)

}

 

function renderItem(item) {

return dragItem(item)

}

 

// 拖拽接收组件

function Bin(props) {

 

const { list, type, title, accept, onDrop, style } = props;

 

const [more, setMore] = useState(false);

 

// 定义拖动源

const [boxes] = useState(list.map(item => {

return { dragItem: item, type: type }

}))

 

const [{ isOver, canDrop }, drop] = useDrop({

accept,

drop: onDrop,

collect: (monitor) => ({

isOver: monitor.isOver(),

canDrop: monitor.canDrop(),

}),

})

const isActive = isOver && canDrop

 

let cardStyle = { ...style }

let alertType = null

if (isActive) {

cardStyle.boxShadow = "0px 0px 12px #1890ff";

alertType = <div style={{ background: "#1890ff", textAlign: 'center', padding: 5 }}>松开鼠标拖拽至此</div>

} else if (canDrop) {

cardStyle.boxShadow = "0px 0px 12px #91d5ff";

alertType = <div style={{ background: "#91d5ff", textAlign: 'center', padding: 5 }}>可拖拽</div>

}

return (

<div ref={drop} >

<Card title={`${title}(${list.length})`} style={cardStyle}>

{canDrop ? alertType : null}

{boxes.map(({ dragItem, type }, index) => {

if (more) {

return <Box key={index} dragItem={dragItem} type={type} />

}

if (index < (firstCount ? firstCount : 5)) {

return <Box key={index} dragItem={dragItem} type={type} />

}

return

})}

{

boxes.length > (firstCount ? firstCount : 5) ?

<div style={{ width: "100%", textAlign: "center", marginTop: 20 }} >

{more ?

<a onClick={() => setMore(false)}>收起更多</a> :

<a onClick={() => setMore(true)}> 存在{boxes.length - (firstCount ? firstCount : 5)}条收起,点此展示更多</a>

}

</div> : null

}

</Card>

</div>

)

}

 

// 可拖拽组件

function Box(props) {

 

const { dragItem, type } = props;

 

const [{ opacity }, drag] = useDrag({

item: { dragItem, type },

collect: (monitor) => ({

opacity: monitor.isDragging() ? 0.4 : 1,

}),

})

return (

<div ref={drag} style={{ opacity }}>

{renderItem(dragItem ? dragItem : {})}

</div>

)

}

 

return (

<DndProvider backend={HTML5Backend}>

<Row>

<div style={{ overflow: 'hidden', clear: 'both' }}>

{dustbins.map((dustbin, index) => (

<Col key={index} span={24 / dustbins.length} style={{ padding: 10 }}>

<Bin

key={index}

list={dustbin.list}

type={dustbin.type}

style={dustbin.style}

title={dustbin.title}

accept={dustbin.accepts}

onDrop={(item) => handleDrop({ dragItem: { ...item.dragItem }, dragTarget: dustbin.type })}

/>

</Col>

))}

</div>

</Row>

</DndProvider>

)

}

export default DragPanel

 

 

2、使用组件

 

import React from 'react'

import DragPanel from './index'

 

const ItemTypes = {

NEW: 'new',

DEAL: 'dear',

FINISH: 'finish',

}

 

function DragDemo(props) {

 

const taskList = {

new: [

{ id: 1, name: "11111" },

{ id: 2, name: "11111222" },

{ id: 3, name: "11111333" }

],

dear: [

{ id: 4, name: "1111144" },

{ id: 5, name: "1111122255" },

{ id: 6, name: "1111133366" },

{ id: 7, name: "111114477" },

{ id: 8, name: "11111222558" },

],

finish: [

{ id: 9, name: "1111144999" },

{ id: 10, name: "1111122251110" },

]

}

 

const dragProps = [

{

accepts: [], //接收拖拽类型

type: ItemTypes.NEW, //列表数据类型

style: { background: '#EDF5D0' },

title: "待办",

list: taskList[ItemTypes.NEW], //列表数据

},

{

accepts: [ItemTypes.NEW],

type: ItemTypes.DEAL,

title: "处理中",

style: { background: '#F5EED0' },

list: taskList[ItemTypes.DEAL]

},

{

accepts: [ItemTypes.NEW, ItemTypes.DEAL],

type: ItemTypes.FINISH,

title: "结束",

list: taskList[ItemTypes.FINISH]

},

]

 

function handleDrag(data) {

console.log(data)

}

 

function dragItem(props) {

return props.name

}

 

return <DragPanel dragProps={dragProps} handleDrag={handleDrag} dragItem={dragItem} />

}

 

export default DragDemo

 

3、实现结果

 

这里拖拽之后位置没有变化是因为没有处理数据,handleDrag方法中就是用来处理拖拽结果的 ,大部分需求是拖拽之后会调用api修改数据然后获取最新数据展示,所以不需要前端修改位置,api修改已经改变了源数据

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
React-beautiful-dnd一个React组件库,用于实现漂亮且易于使用的拖放列表。要实现一个列表拖放,需要执行以下步骤: 1. 安装react-beautiful-dnd: ``` npm install --save react-beautiful-dnd ``` 2. 导入DragDropContext、Droppable和Draggable组件: ```javascript import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'; ``` 3. 创建状态并为每个列表项目分配一个唯一标识符: ```javascript const [items, setItems] = useState([ { id: "1", content: "Item 1" }, { id: "2", content: "Item 2" }, { id: "3", content: "Item 3" }, { id: "4", content: "Item 4" }, { id: "5", content: "Item 5" }, { id: "6", content: "Item 6" } ]); ``` 4. 创建渲染函数以呈现每个拖动项目: ```javascript const renderItems = () => { return items.map((item, index) => ( <Draggable key={item.id} draggableId={item.id} index={index}> {(provided, snapshot) => ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)}> {item.content} </div> )} </Draggable> )); }; ``` 5. 创建渲染函数以呈现拖放列表: ```javascript const renderList = () => { return ( <DragDropContext onDragEnd={onDragEnd}> <Droppable droppableId="items"> {(provided, snapshot) => ( <div {...provided.droppableProps} ref={provided.innerRef} style={getListStyle(snapshot.isDraggingOver)}> {renderItems()} {provided.placeholder} </div> )} </Droppable> </DragDropContext> ); }; ``` 6. 创建onDragEnd函数以处理拖动项目: ```javascript const onDragEnd = result => { if (!result.destination) { return; } const itemsCopy = [...items]; const [reorderedItem] = itemsCopy.splice(result.source.index, 1); itemsCopy.splice(result.destination.index, 0, reorderedItem); setItems(itemsCopy); }; ``` 7. 创建样式函数以获取拖动和放置元素的样式: ```javascript const getItemStyle = (isDragging, draggableStyle) => ({ userSelect: 'none', padding: 16, margin: `0 0 ${8}px 0`, border: isDragging ? '2px solid #000' : 'none', ...draggableStyle }); const getListStyle = isDraggingOver => ({ background: isDraggingOver ? 'lightblue' : '#eee', padding: 8, width: 250 }); ``` 最后,用renderList函数渲染列表,将其放在你的React组件中,就可以开始拖放操作了!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值