前言
自己通过HTML提供的拖拽API实现的拖拽功能,存在的问题:拖拽过程没有过度、输入框不能通过鼠标全选; 所以接入第三方插件库去实现。
组件
DragDropContext
必填props
- onDragEnd: 返回拖拽的信息(result),如开始位置(result.source.index)、目标位置(result.destination.index)
Droppable
必填props
- droppableId: 必填,保证唯一性(如果有多个同时需要实现拖拽的组件,详见)
可选props
type
: ATypeId(string)
that can be used to simply accept only the specified class of<Draggable />
.<Draggable />
s always inherit type from the<Droppable />
they are defined in. For example, if you use the typePERSON
then it will only allow<Draggable />
s of typePERSON
to be dropped on itself.<Draggable />
s of typeTASK
would not be able to be dropped on a<Droppable />
with typePERSON
. If notype
is provided, it will be set to'DEFAULT'
.isDropDisabled
: A flag to control whether or not dropping is currently allowed on the<Droppable />
. You can use this to implement your own conditional dropping logic. It will default tofalse
.isCombineEnabled
: A flag to control whether or not all theDraggables
in the list will be able to be combined with. It will default tofalse
.direction
: The direction in which items flow in this droppable. Options arevertical
(default) andhorizontal
.ignoreContainerClipping
: When a<Droppable />
is inside a scrollable container its area is constrained so that you can only drop on the part of the<Droppable />
that you can see. Setting this prop opts out of this behavior, allowing you to drop anywhere on a<Droppable />
even if it's visually hidden by a scrollable parent. The default behavior is suitable for most cases so odds are you'll never need to use this prop, but it can be useful if you've got very long<Draggable />
s inside a short scroll container. Keep in mind that it might cause some unexpected behavior if you have multiple<Droppable />
s inside scroll containers on the same page.mode
:standard
(default) orvirtual
. Used to designate a list as a virtual list. See our virtual lists patternrenderClone
: used to render a clone (replacement) of the dragging<Draggable />
while a drag is occurring. See our reparenting guide for usage details. A clone must be used for virtual lists. You can use a clone without using virtual listsgetContainerForClone
: a function that returns the containing element (parent element) for a clone during a drag. See our reparenting guide.
标签必须包裹一个函数,并且返回react元素
<Droppable droppableId="droppable-1">
{(provided, snapshot) => ({
/*...*/
})}
</Droppable>
该函数提供两个参数
provided说明
provided.innerRef
: In order for the droppable to function correctly, you must bind theprovided.innerRef
to the highest possible DOM node in theReactElement
. We do this in order to avoid needing to useReactDOM
to look up your DOM node.
For more information on using
innerRef
see our usinginnerRef
guide
provided.placeholder
: This is used to create space in the<Droppable />
as needed during a drag. This space is needed when a user is dragging over a list that is not the home list. Please be sure to put the placeholder inside of the component for which you have provided the ref. We need to increase the size of the<Droppable />
itself.provided.droppableProps (DroppableProps)
: This is an Object that contains properties that need to be applied to a Droppable element. It needs to be applied to the same element that you applyprovided.innerRef
to. It currently containsdata
attributes that we use for styling and lookups.
snapshot说明
通过这个参数暴露出的属性,可以根据需要设置一些样式交互,例如正在拖拽中的元素效果。
Draggable
栗子
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
// fake data generator
const getItems = count =>
Array.from({ length: count }, (v, k) => k).map(k => ({
id: `item-${k}`,
content: `item ${k}`
}));
// a little function to help us with reordering the result
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
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
});
class App extends Component {
constructor(props) {
super(props);
this.state = {
items: getItems(10)
};
this.onDragEnd = this.onDragEnd.bind(this);
}
onDragEnd(result) {
// dropped outside the list
if (!result.destination) {
return;
}
const items = reorder(
this.state.items,
result.source.index,
result.destination.index
);
this.setState({
items
});
}
// Normally you would want to split things out into separate components.
// But in this example everything is just done in one place for simplicity
render() {
return (
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={getListStyle(snapshot.isDraggingOver)}
>
{this.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}
<input />
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
}
// Put the thing into the DOM!
ReactDOM.render(<App />, document.getElementById("root"));
效果图
报错
外层元素缺少ref
A setup problem was encountered.> Invariant failed: provided.innerRef has not been provided with a HTMLElement.
- 控制台报错
- 无法拖动
warning
Droppable内缺少provided.placeholder
官方说明
provided.placeholder
: This is used to create space in the <Droppable />
as needed during a drag. This space is needed when a user is dragging over a list that is not the home list. Please be sure to put the placeholder inside of the component for which you have provided the ref. We need to increase the size of the <Droppable />
itself.
最后
拖拽控制台会报这个警告,目前还不知道对组件功能有什么影响