React-beautiful-dnd 实例demo
src/routes/IndexPage.js
import React, { Component } from "react";
// import '@atlaskit/css-reset'
import { DragDropContext } from "react-beautiful-dnd";
import styled from "styled-components";
import initialData from "../components/todoData";
import Column from "../components/column";
const Container = styled.div`
display: flex;
`;
export default class IndexPage extends Component {
state = initialData;
onDragEnd = (result) => {
const { destination, source, draggableId } = result;
// 如果没有拖动直接结束
if (!destination) {
return;
}
// 如果拖动列没有改变并且顺序没有改变则直接结束
if (
destination.droppableId === source.droppableId &&
destination.index === source.index
) {
return;
}
const start = this.state.columns[source.droppableId];
const finish = this.state.columns[destination.droppableId];
console.log("start", start);
console.log("finish", finish);
// 如果在当前列拖动 在当前列重排列
if (start === finish) {
const newTaskIds = Array.from(start.taskIds);
newTaskIds.splice(source.index, 1);
newTaskIds.splice(destination.index, 0, draggableId);
const newColumn = {
...start,
taskIds: newTaskIds,
};
const newState = {
...this.state,
columns: {
...this.state.columns,
[newColumn.id]: newColumn,
},
};
this.setState(newState);
return;
}
// 拖动至非当前列的操作
const startTaskIds = Array.from(start.taskIds);
// 从拖动源头列删除该项
startTaskIds.splice(source.index, 1);
const newStart = {
...start,
taskIds: startTaskIds,
};
// 添加至目标列表
const finishTaskIds = Array.from(finish.taskIds);
finishTaskIds.splice(destination.index, 0, draggableId);
const newFinish = {
...finish,
taskIds: finishTaskIds,
};
// 更新state
const newState = {
...this.state,
columns: {
...this.state.columns,
[newStart.id]: newStart,
[newFinish.id]: newFinish,
},
};
this.setState(newState);
};
render() {
return (
<DragDropContext onDragEnd={this.onDragEnd}>
<Container>
{this.state.columnOrder.map((columnId) => {
const column = this.state.columns[columnId];
const tasks = column.taskIds.map(
(taskId) => this.state.tasks[taskId]
);
return <Column key={column.id} column={column} tasks={tasks} />;
})}
</Container>
</DragDropContext>
);
}
}
colum.js
import React, { Component } from "react";
import styled from "styled-components";
import Task from "./task";
import { Droppable } from "react-beautiful-dnd";
const Container = styled.div`
margin: 8px;
border: 1px solid lightgrey;
border-radius: 2px;
width: 220px;
display: flex;
flex-direction: column;
`;
const Title = styled.h3`
padding: 8px;
`;
const TaskList = styled.div`
padding: 8px;
transition: background-color 0.2s ease;
background-color: ${(props) => (props.isDraggingOver ? "skyblue" : "white")};
flex-grow: 1;
min-height: 100px;
`;
export default class Column extends Component {
render() {
return (
<Container>
<Title>{this.props.column.title}</Title>
<Droppable droppableId={this.props.column.id} type="TASK">
{(provided, snapshot) => (
<TaskList
ref={provided.innerRef}
{...provided.droppableProps}
isDraggingOver={snapshot.isDraggingOver}
>
{this.props.tasks.map((task, index) => (
<Task key={task.id} task={task} index={index} />
))}
{provided.placeholder}
</TaskList>
)}
</Droppable>
</Container>
);
}
}
task.js
import React, { Component } from "react";
import styled from "styled-components";
import { Draggable } from "react-beautiful-dnd";
const Container = styled.div`
border: 1px solid lightgrey;
border-radius: 2px;
padding: 8px;
margin-bottom: 8px;
transition: background-color 0.2s ease;
background-color: ${(props) =>
props.isDragDisabled
? "lightgrey"
: props.isDragging
? "lightgreen"
: "white"};
`;
export default class Task extends Component {
render() {
// const isDragDisabled = this.props.task.id === 'task-1'
return (
<Draggable
draggableId={this.props.task.id}
index={this.props.index}
// isDragDisabled={isDragDisabled}
>
{(provided, snapshot) => {
console.log("provided", provided);
console.log("snapshot", snapshot);
return (
<Container
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
isDragging={snapshot.isDragging}
>
{this.props.task.content}
</Container>
);
}}
</Draggable>
);
}
}
data.js
const initialData = {
tasks: {
"task-1": { id: "task-1", content: "吃饭" },
"task-2": { id: "task-2", content: "睡觉" },
"task-3": { id: "task-3", content: "打豆豆" },
"task-4": { id: "task-4", content: "coding" },
},
columns: {
"column-1": {
id: "column-1",
title: "TODO",
taskIds: ["task-1", "task-2", "task-3", "task-4"],
},
"column-2": {
id: "column-2",
title: "TODOING",
taskIds: [],
},
"column-3": {
id: "column-3",
title: "FINISH",
taskIds: [],
},
},
columnOrder: ["column-1", "column-2", "column-3"],
};
export default initialData;