1.动态数量的列表(带有功能组件)和删除项目的能力
import React, { useState } from 'react'
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'
// fake data generator
const getItems = (count, offset = 0) =>
Array.from({ length: count }, (v, k) => k).map((k) => ({
id: `item-${k + offset}-${new Date().getTime()}`,
content: `item ${k + offset}`,
}))
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list)
const [removed] = result.splice(startIndex, 1)
result.splice(endIndex, 0, removed)
return result
}
/**
* Moves an item from one list to another list.
*/
const move = (source, destination, droppableSource, droppableDestination) => {
const sourceClone = Array.from(source)
const destClone = Array.from(destination)
const [removed] = sourceClone.splice(droppableSource.index, 1)
destClone.splice(droppableDestination.index, 0, removed)
const result = {}
result[droppableSource.droppableId] = sourceClone
result[droppableDestination.droppableId] = destClone
return result
}
const grid = 8
const getItemStyle = (isDragging, draggableStyle) => ({
// some basic styles to make the items look a bit nicer
userSelect: 'none',
padding: grid * 2,
margin: `0 0 ${grid}px 0`,
// change background colour if dragging
background: isDragging ? 'lightgreen' : 'grey',
// styles we need to apply on draggables
...draggableStyle,
})
const getListStyle = (isDraggingOver) => ({
background: isDraggingOver ? 'lightblue' : 'lightgrey',
padding: grid,
width: 250,
})
function DynamicDrag() {
const [state, setState] = useState([getItems(10), getItems(5, 10)])
function onDragEnd(result) {
const { source, destination } = result
// dropped outside the list
if (!destination) {
return
}
const sInd = +source.droppableId
const dInd = +destination.droppableId
if (sInd === dInd) {
const items = reorder(state[sInd], source.index, destination.index)
const newState = [...state]
newState[sInd] = items
setState(newState)
} else {
const result = move(state[sInd], state[dInd], source, destination)
const newState = [...state]
newState[sInd] = result[sInd]
newState[dInd] = result[dInd]
setState(newState.filter((group) => group.length))
}
}
return (
<div>
<button
type="button"
onClick={() => {
setState([...state, []])
}}
>
Add new group
</button>
<button
type="button"
onClick={() => {
setState([...state, getItems(1)])
}}
>
Add new item
</button>
<div style={{ display: 'flex' }}>
<DragDropContext onDragEnd={onDragEnd}>
{state.map((el, ind) => (
<Droppable key={ind} droppableId={`${ind}`}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
style={getListStyle(snapshot.isDraggingOver)}
{...provided.droppableProps}
>
{el.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)}
>
<div
style={{
display: 'flex',
justifyContent: 'space-around',
}}
>
{item.content}
<button
type="button"
onClick={() => {
const newState = [...state]
newState[ind].splice(index, 1)
setState(newState.filter((group) => group.length))
}}
>
delete
</button>
</div>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
))}
</DragDropContext>
</div>
</div>
)
}
export default DynamicDrag
两个项目之间的拖拽
import React, { useState } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
const getItems = (count, offset = 0) =>
Array.from({ length: count }, (v, k) => k).map((k) => ({
id: `item-${k + offset}`,
content: `item ${k + offset}`,
}));
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
};
const move = (source, destination, droppableSource, droppableDestination) => {
const sourceClone = Array.from(source);
const destClone = Array.from(destination);
const [removed] = sourceClone.splice(droppableSource.index, 1);
destClone.splice(droppableDestination.index, 0, removed);
const result = {};
result[droppableSource.droppableId] = sourceClone;
result[droppableDestination.droppableId] = destClone;
return result;
};
const grid = 8;
const getItemStyle = (isDragging, draggableStyle) => ({
userSelect: 'none',
padding: grid * 2,
margin: `0 0 ${grid}px 0`,
background: isDragging ? 'lightgreen' : 'grey',
...draggableStyle,
});
const getListStyle = (isDraggingOver) => ({
background: isDraggingOver ? 'lightblue' : 'lightgrey',
padding: grid,
width: 250,
});
const Nest = ()=> {
const [state, setState] = useState({
items: getItems(10),
selected: getItems(5, 10),
})
const id2List = {
droppable: 'items',
droppable2: 'selected',
};
const getList = (id) => state[id2List[id]];
const onDragEnd = (result) => {
const { source, destination } = result;
if (!destination) {
return;
}
if (source.droppableId == destination.droppableId) {
const items = reorder(getList(source.droppableId), source.index, destination.index);
let stateItem = { items };
if (source.droppableId === 'droppable2') {
stateItem = { selected: items };
}
setState({...state, ...stateItem});
} else {
const result = move(
getList(source.droppableId),
getList(destination.droppableId),
source,
destination,
);
setState({
items: result.droppable,
selected: result.droppable2,
});
}
};
return (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<div ref={provided.innerRef} style={getListStyle(snapshot.isDraggingOver)}>
{state.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>
))}
{provided.placeholder}
</div>
)}
</Droppable>
<Droppable droppableId="droppable2">
{(provided, snapshot) => (
<div ref={provided.innerRef} style={getListStyle(snapshot.isDraggingOver)}>
{state.selected?.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>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
export default Nest;
拖拽投票组件,拖动至指定容器,位置互换
import React from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { countyUnits } from './constant';
import styles from './VoteByDnd.less';
const grid = 8;
const getIndex = (droppableId) => {
const endDroppableIdArray = droppableId.split('-');
const droppableIndex = parseInt(endDroppableIdArray[2], 10);
return droppableIndex;
};
const reorder = (list, startDroppablDeId, endDroppablDeId) => {
const result = JSON.parse(JSON.stringify(list));
const startIndex = getIndex(startDroppablDeId);
const endIndex = getIndex(endDroppablDeId);
result[startIndex] = list[endIndex];
result[endIndex] = list[startIndex];
return result;
};
const setItemStyle = (isDragging, draggableStyle) => {
const styleOnject = {
userSelect: 'none',
padding: grid * 2,
margin: `0 0 ${grid}px 0`,
width: 70,
height: 70,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'all 0.5s',
opacity: isDragging ? '1' : '0',
backgroundColor: isDragging ? 'rgba(93,173,243,0.5)' : 'rgba(93,173,243,1)',
...draggableStyle,
};
return styleOnject;
};
class VoteByDnd extends React.Component {
constructor(props) {
super(props);
this.state = {
items: countyUnits,
};
this.onDragEnd = this.onDragEnd.bind(this);
}
onDragEnd(result) {
console.log('拖拽结束result', result);
if (!result.destination) {
return;
}
const { items: prevItems } = this.state;
const items = reorder(prevItems, result.source.droppableId, result.destination.droppableId);
this.setState({
items,
isDragging: false,
});
}
onDragStart = (result) => {
console.log('拖拽开始result', result);
this.setState({
isDragging: true,
});
};
renderChildDrag = (item, index) => {
const childElement = (
<Droppable droppableId={`child-droppable-${index}`}>
{(provided, snapshot) => (
<div
//provided.droppableProps应用的相同元素.
{...provided.droppableProps}
// 为了使 droppable 能够正常工作必须 绑定到最高可能的DOM节点中provided.innerRef.
ref={provided.innerRef}
// style={getListStyle(snapshot)}
// className={isDragging ? styles.childBoxHidden : styles.childBoxShow}
className={styles.childBoxShow}
>
<Draggable key={index} draggableId={`child-draggableId-${index}`} index={index}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={setItemStyle(snapshot.isDragging, provided.draggableProps.style)}
>
{`${item}`}
</div>
)}
</Draggable>
{provided.placeholder}
</div>
)}
</Droppable>
);
return childElement;
};
render() {
return (
<div className={styles.root}>
<DragDropContext onDragEnd={this.onDragEnd} onDragStart={this.onDragStart}>
<Droppable droppableId="droppable" type="father">
{(provided, snapshot) => (
<div
//provided.droppableProps应用的相同元素.
{...provided.droppableProps}
// 为了使 droppable 能够正常工作必须 绑定到最高可能的DOM节点中provided.innerRef.
ref={provided.innerRef}
// style={getListStyle(snapshot)}
className={styles.flexBox}
>
{this.state.items.map((item, index) => (
<Draggable key={index} draggableId={`index`} index={index} isDragDisabled>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className={styles.flexItem}
>
<div className={styles.tempTitle}> {item} </div>
{this.renderChildDrag(item, index)}
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</div>
);
}
}
export default VoteByDnd;
const countyUnitsString ='上城、下城、江干、拱墅、西湖、滨江、钱塘、景区、萧山、余杭、富阳、临安、桐庐、淳安、建德'
export const countyUnits = countyUnitsString.split('、')
.root {
.flexBox {
display: flex;
flex-wrap: wrap;
width: 400px;
.flexItem {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 90px;
height: 90px;
margin: 0 10px 10px 0;
color: #fff;
font-size: 18px;
background-color: #5dadf3;
}
}
.tempTitle {
position: absolute;
}
.childBoxShow {
width: 90px;
height: 90px;
opacity: 1;
}
}