React拖拽插件:react-beautiful-dnd 中文文档及示例

本篇文章主要介绍react-beautiful-dnd,它是基于react的拖拽插件
接下来会从以下几个方面来介绍react-beautiful-dnd

  1. 安装使用
  2. API介绍
  3. Example

1. 安装使用

首先我们需要安装react-beautiful-dnd

# yarn
yarn add react-beautiful-dnd

# npm
npm install react-beautiful-dnd --save

使用时:

import { DragDropContext } from 'react-beautiful-dnd';

2. API介绍

DragDropContext

DragDropContext是拖拽部分的根组件,Droppable Draggable都需要包含在DragDropContext中。

In order to use drag and drop, you need to have the part of your React tree that you want to be able to use drag and drop in wrapped in a . It is advised to just wrap your entire application in a . Having nested 's is not supported. You will be able to achieve your desired conditional dragging and dropping using the props of and . You can think of as having a similar purpose to the react-redux Provider component. A content-security-protection nonce attribute is added to the injected style tags if provided.

在官方给出的解释中,如果想要实现拖拽,你需要有一个React Tree,将想要拖拽的部分包含在DragDropContext中,有嵌套关系的 <DragDropContext /> 是不支持的
接下来我们看一下DragDropContext中的参数和支持的方法。

type Responders = {|
  // optional
  onBeforeCapture?: OnBeforeCaptureResponder
  onBeforeDragStart?: OnBeforeDragStartResponder,
  onDragStart?: OnDragStartResponder,
  onDragUpdate?: OnDragUpdateResponder,
  // required
  onDragEnd: OnDragEndResponder,
|};

import type { Node } from 'react';

type Props = {|
  ...Responders,
  // We do not technically need any children for this component
  children: Node | null,
  // Read out by screen readers when focusing on a drag handle
  dragHandleUsageInstructions?: string,
  // Used for strict content security policies
  nonce?: string,
  // Used for custom sensors
  sensors?: Sensor[],
  enableDefaultSensors?: ?boolean,
|};

从上面给出的事件和参数,我们可以整理出DragDropContext的常用的事件和属性

参数 是否必须 类型 说明
onBeforeCapture function 在捕获之前
onBeforeDragStart function 在拖动开始之前
onDragStart function 在拖动开始时
onDragUpdate function 在拖动开始时
onDragEnd function 在拖动结束时

代码示例:

const DragContainerCom = () => {
    const onBeforeCapture = () => {}
    const onBeforeDragStart = () => {}
    const onDragStart = () => {}
    const onDragUpdate = () => {}
    const onDragEnd = () =>{}

    return <div className={styles.dragContainer}>
        <DragDropContext  
            onBeforeCapture={onBeforeCapture}
            onBeforeDragStart={onBeforeDragStart}
            onDragStart={onDragStart}
            onDragUpdate={onDragUpdate}
            onDragEnd={onDragEnd}>
            <div>这是可以拖拽的组件</div>
        </DragDropContext>
    </div>
}

这个时候的卡片还不能被拖动。因为我们没有在DragDropContext中放可拖拽的单元。
image

2. Draggable

Draggable我们使用这个API来接收拖拽的组件,使组件可以放置在容器中
从官方给出的定义来看 Draggable包裹的组件可以被拖拽到Droppable容器中。每个Droppable必须包含一个Draggable

components can be dragged around and dropped onto s. A must always be contained within a . It is possible to reorder a within its home or move to another . It is possible because a is free to control what it allows to be dropped on it.

接下来我们可以看看官方给出的Draggable需要的参数

import type { Node } from 'react';

type Props = {|
  // required
  draggableId: DraggableId,
  index: number,
  children: DraggableChildrenFn,
  // optional
  isDragDisabled: ?boolean,
  disableInteractiveElementBlocking: ?boolean,
  shouldRespectForcePress: ?boolean,
|};
属性 是否必须 数据类型
draggableId string
index number
isDragDisabled boolean
disableInteractiveElementBlocking boolean
shouldRespectForcePress boolean
  • draggableId: 一个需要 DraggableId(string)唯一标识的Draggable为应用程序. 请不要更改此 Props - 特别是在拖动时.
  • index : 一个需要 number它与Draggable的顺序相匹配在Droppable里面. 它只是简单的索引Draggable在列表中. 该index在一个内部需要是唯一的Droppable, 但不需要是唯一的Droppables. 通常情况下index价值将是简单的index由Array.prototype.map函数提供:
import { Draggable } from 'react-beautiful-dnd';
<Draggable draggableId="draggable-1" index={0}>
  {(provided, snapshot) => (
    <div
      ref={provided.innerRef}
      {...provided.draggableProps}
      {...provided.dragHandleProps}
    >
      <h4>My draggable</h4>
    </div>
  )}
</Draggable>;
2.1 子函数(render Props/function as child)

draggable的子函数必须返回一个reactNode

<Draggable draggableId="draggable-1" index={0}>
  {(provided, snapshot) => (
    <div
      ref={provided.innerRef}
      {...provided.draggableProps}
      {...provided.dragHandleProps}
    >
      Drag me!
    </div>
  )}
</Draggable>

上述函数提供了三个参数:

type DraggableProvided = {|
  innerRef: (HTMLElement) => void,
  draggableProps: DraggableProps,
  // will be null if the draggable is disabled
  dragHandleProps: ?DragHandleProps,
|};

innerRef:为了使Draggable正确运行,必须将innerRef函数绑定到ReactElement,希望将其视为Draggable节点。这样做是为了避免使用ReactDOM查找DOM节点。
draggableProps:这是一个包含数据属性和内联样式的对象。此对象需要应用于将innerRef应用于的同一节点。它控制可拖动控件在拖动和不拖动时的移动。可添加自己的样式到DraggableProps-style, 但请不要删除或替换任何属性
draggableProps:这是用来拖动整个Draggable的。这个节点通常与Draggable相同,但有时也可能是Draggable的子节点。拖柄道具需要应用到您想要作为拖柄的节点。这是一些需要应用到Draggable节点的道具。最简单的方法是将道具分散到可拖动节点上({…provider.draghandleprops})。但是,如果还需要回复他们,你给这些道具打补丁。当isDragDisabled被设置为true时,DragHandleProps将为null。

2.2 子函数的Snapshot(DraggableStateSnapshot)
type DraggableStateSnapshot = {|
  // Set to true if a Draggable is being actively dragged, or if it is drop animating
  // Both active dragging and the drop animation are considered part of the drag
  // *Generally this is the only property you will be using*
  isDragging: boolean,
  // Set to true if a Draggable is drop animating. Not every drag and drop interaction
  // as a drop animation. There is no drop animation when a Draggable is already in its final
  // position when dropped. This is commonly the case when dragging with a keyboard
  isDropAnimating: boolean,
  // Information about a drop animation
  dropAnimation: ?DropAnimation
  // What Droppable (if any) the Draggable is currently over
  draggingOver: ?DroppableId,
  // the id of a draggable that you are combining with
  combineWith: ?DraggableId,
  // if something else is dragging and you are a combine target, then this is the id of the item that is dragging
  combineTargetFor: ?DraggableId,
  // There are two modes that a drag can be in
  // 'FLUID': everything is done in response to highly granular input (eg mouse)
  // 'SNAP': items snap between positions (eg keyboard);
  mode: ?MovementMode,
|};

示例2:

<Draggable draggableId="draggable-1" index={0}>
  {(provided, snapshot) => {
    const style = {
      backgroundColor: snapshot.isDragging ? 'blue' : 'grey',
      ...provided.draggableProps.style,
    };

    return (
      <div
        ref={provided.innerRef}
        {...provided.draggableProps}
        {...provided.dragHandleProps}
        style={style}
      >
        Drag me!
      </div>
    );
  }}
</Draggable>
3. Droppable

Droppable components can be dropped on by a Draggable. They also contain Draggables. A Draggable must be contained within a Droppable.

官方的意思是在拖拽的组件需要被包含在<Drppable/>。拖拽的容器 <Draggable />也会包含在<Drppable/>
示例3

import { Droppable } from 'react-beautiful-dnd';

<Droppable droppableId="droppable-1" type="PERSON">
  {(provided, snapshot) => (
    <div
      ref={provided.innerRef}
      style={{ backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey' }}
      {...provided.droppableProps}
    >
      <h2>I am a droppable!</h2>
      {provided.placeholder}
    </div>
  )}
</Droppable>;

接下来看一下Droppable props

import type { Node } from 'react';
type Props = {|
  // required
  droppableId: DroppableId,
  // optional
  type?: TypeId,
  mode?: DroppableMode,
  isDropDisabled?: boolean,
  isCombineEnabled?: boolean,
  direction?: Direction,
  ignoreContainerClipping?: boolean,
  renderClone?: DraggableChildrenFn,
  getContainerForClone?: () => HTMLElement,
  children: (DroppableProvided, DroppableStateSnapshot) => Node,
|};
type DroppableMode = 'standard' | 'virtual';
type Direction = 'horizontal' | 'vertical';

参数说明:
droppableId:一个需要 DroppableId(string)唯一标识该应用程序的可投入程序. 请不要更改此 Props , 特别是在拖动时.
type: 可选的 TypeId(string)可以用来简单地接受一类Draggable. 例如,如果您使用该类型PERSON那么它只会允许Draggable类型的PERSON放下自己. Draggable类型的TASK将无法被放在Droppable与类型PERSON上. 如果不提供type,它将被设置为'DEFAULT'. 目前来说Draggable的type在Droppable之内 一定是一样. 如果有一个有效的用例,这个限制在将来可能会放松.

3.1 子函数(render Props/function as child)

Droppable的React子节点必须是返回react元素的函数。

<Droppable droppableId="droppable-1">
  {(provided, snapshot) => ({
    /*...*/
  })}
</Droppable>

该函数有两个参数
proviede: (DroppableProvided)

import type { Node } from 'react';
type DroppableProvided = {|
  innerRef: (?HTMLElement) => void,
  droppableProps: DroppableProps,
  placeholder: ?Node,
|};

type DroppableProps = {|
  // used for shared global styles
  'data-rbd-droppable-context-id': ContextId,
  // Used to lookup. Currently not used for drag and drop lifecycle
  'data-rbd-droppable-id': DroppableId,
|};

参数说明
provided.innerRef : 为了使droppable正确运行,必须绑定所提供的。innerRef指向ReactElement中尽可能高的DOM节点。这样是为了避免使用ReactDOM查找DOM节点。
provided.placeholder :用于在拖动过程中根据需要在< Droppable />中创建空格。当用户拖动非主列表的列表时,需要此空间。请确保将占位符放在您提供ref的组件中。我们需要增加本身的大小。
provided.droppableProps (DroppableProps) :这是一个包含需要应用于可删除元素的属性的对象。它需要应用到与应用provided.innerRef相同的元素。它目前包含用于样式化和查找的数据属性。
示例3.1

<Droppable droppableId="droppable-1">
  {(provided, snapshot) => (
    <div ref={provided.innerRef} {...provided.droppableProps}>
      Good to go
      {provided.placeholder}
    </div>
  )}
</Droppable>

snapshot: (DroppableStateSnapshot)

type DroppableStateSnapshot = {|
  // Is the Droppable being dragged over?
  // Is the Droppable being dragged over?
  isDraggingOver: boolean,
  // What is the id of the draggable that is dragging over the Droppable?
  // Is the Droppable being dragged over?
  draggingOverWith: ?DraggableId,
  // What is the id of the draggable that is dragging from this list?
  // Useful for styling the home list when not being dragged over
  // What is the id of the draggable that is dragging from this list?
  // Useful for styling the home list when not being dragged over
  draggingFromThisWith: ?DraggableId,
  // Whether or not the placeholder is actively being used.
  // This is useful information when working with virtual lists
  // (See our virtual list pattern)
  // Whether or not the placeholder is actively being used.
  // This is useful information when working with virtual lists
  // (See our virtual list pattern)
  isUsingPlaceholder: boolean,
|};

注意:

  • Droppable 可以作为DraggableDragDropContext的子组件。
  • Draggable 必须包含在<Droppable/> 中,即<Draggable />,只能作为<Droppable /> 的子组件
posted @ 2023-12-19 14:23  前端加油站  阅读(6057)  评论(0编辑  收藏  举报