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 } = 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 [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 dragText = ''

if (isActive) {

cardStyle.background = 'darkgreen'

dragText = '鬆開鼠標拖拽至此'

} else if (canDrop) {

cardStyle.background = 'darkkhaki'

dragText = '可拖拽'

}

 

return (

<div ref={drop} >

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

{dragText ? <div style={{ textAlign: "center", paddingBottom: 5 }}>{dragText}</div> : null}

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

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

})}

</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)}

</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修改已經改變了源數據

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章