React拖拽插件:react-beautiful-dnd 中文文档及示例
<p>本篇文章主要介绍<code>react-beautiful-dnd</code>,它是基于<code>react</code>的拖拽插件<br>接下来会从以下几个方面来介绍<code>react-beautiful-dnd</code></p>
<ol>
<li>安装使用</li>
<li>API介绍</li>
<li>Example</li>
</ol>
<h4 id="1-安装使用">1. 安装使用</h4>
<p>首先我们需要安装<code>react-beautiful-dnd</code></p>
<pre><code># yarn
yarn add react-beautiful-dnd
# npm
npm install react-beautiful-dnd --save
</code></pre>
<p>使用时:</p>
<pre><code>import { DragDropContext } from 'react-beautiful-dnd';
</code></pre>
<h4 id="2-api介绍">2. API介绍</h4>
<h6 id="dragdropcontext">DragDropContext</h6>
<p><code>DragDropContext</code>是拖拽部分的根组件,<code>Droppable </code>和<code>Draggable</code>都需要包含在<code>DragDropContext</code>中。</p>
<blockquote>
<p>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 <dragdropcontext>. It is advised to just wrap your entire application in a <dragdropcontext>. Having nested <dragdropcontext>'s is not supported. You will be able to achieve your desired conditional dragging and dropping using the props of <droppable> and <draggable>. You can think of <dragdropcontext> 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.</dragdropcontext></draggable></droppable></dragdropcontext></dragdropcontext></dragdropcontext></p>
</blockquote>
<p>在官方给出的解释中,如果想要实现拖拽,你需要有一个React Tree,将想要拖拽的部分包含在<code>DragDropContext</code>中,<strong>有嵌套关系的<code> <DragDropContext /></code> 是不支持的</strong>。<br>
接下来我们看一下<code>DragDropContext</code>中的参数和支持的方法。</p>
<pre><code>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,
|};
</code></pre>
<p>从上面给出的事件和参数,我们可以整理出<code>DragDropContext</code>的常用的事件和属性</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>是否必须</th>
<th>类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>onBeforeCapture</td>
<td>否</td>
<td>function</td>
<td>在捕获之前</td>
</tr>
<tr>
<td>onBeforeDragStart</td>
<td>否</td>
<td>function</td>
<td>在拖动开始之前</td>
</tr>
<tr>
<td>onDragStart</td>
<td>否</td>
<td>function</td>
<td>在拖动开始时</td>
</tr>
<tr>
<td>onDragUpdate</td>
<td>否</td>
<td>function</td>
<td>在拖动开始时</td>
</tr>
<tr>
<td>onDragEnd</td>
<td>否</td>
<td>function</td>
<td>在拖动结束时</td>
</tr>
</tbody>
</table>
<p>代码示例:</p>
<pre><code>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>
}
</code></pre>
<p>这个时候的卡片还不能被拖动。因为我们没有在<code>DragDropContext</code>中放可拖拽的单元。<br>
<img src="https://img2023.cnblogs.com/blog/1234038/202312/1234038-20231219100926889-1560603122.png"></p>
<h6 id="2-draggable">2. Draggable</h6>
<p><code>Draggable</code>我们使用这个API来接收拖拽的组件,使组件可以放置在容器中<br>
从官方给出的定义来看 <code>Draggable</code>包裹的组件可以被拖拽到<code>Droppable</code>容器中。每个<code>Droppable</code>必须包含一个<code>Draggable</code></p>
<blockquote>
<p><draggable> components can be dragged around and dropped onto <droppable>s. A <draggable> must always be contained within a <droppable>. It is possible to reorder a <draggable> within its home <droppable> or move to another <droppable>. It is possible because a <droppable> is free to control what it allows to be dropped on it.</droppable></droppable></droppable></draggable></droppable></draggable></droppable></draggable></p>
</blockquote>
<p>接下来我们可以看看官方给出的<code>Draggable</code>需要的参数</p>
<pre><code>import type { Node } from 'react';
type Props = {|
// required
draggableId: DraggableId,
index: number,
children: DraggableChildrenFn,
// optional
isDragDisabled: ?boolean,
disableInteractiveElementBlocking: ?boolean,
shouldRespectForcePress: ?boolean,
|};
</code></pre>
<table>
<thead>
<tr>
<th>属性</th>
<th>是否必须</th>
<th>数据类型</th>
</tr>
</thead>
<tbody>
<tr>
<td>draggableId</td>
<td>是</td>
<td>string</td>
</tr>
<tr>
<td>index</td>
<td>是</td>
<td>number</td>
</tr>
<tr>
<td>isDragDisabled</td>
<td>否</td>
<td>boolean</td>
</tr>
<tr>
<td>disableInteractiveElementBlocking</td>
<td>否</td>
<td>boolean</td>
</tr>
<tr>
<td>shouldRespectForcePress</td>
<td>否</td>
<td>boolean</td>
</tr>
</tbody>
</table>
<ul>
<li><code>draggableId</code>: 一个需要<code> DraggableId(string)</code>唯一标识的<code>Draggable</code>为应用程序. 请不要更改此<code> Props</code> - 特别是在拖动时.</li>
<li><code>index</code> : 一个需要 <code>number</code>它与<code>Draggable</code>的顺序相匹配在<code>Droppable</code>里面. 它只是简单的索引<code>Draggable</code>在列表中. 该index在一个内部需要是唯一的<code>Droppable</code>, 但不需要是唯一的<code>Droppables</code>. 通常情况下index价值将是简单的index由Array.prototype.map函数提供:</li>
</ul>
<pre><code>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>;
</code></pre>
<h6 id="21-子函数render-propsfunction-as-child">2.1 子函数(render Props/function as child)</h6>
<p><code>draggable</code>的子函数必须返回一个reactNode</p>
<pre><code><Draggable draggableId="draggable-1" index={0}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
Drag me!
</div>
)}
</Draggable>
</code></pre>
<p>上述函数提供了三个参数:</p>
<pre><code>type DraggableProvided = {|
innerRef: (HTMLElement) => void,
draggableProps: DraggableProps,
// will be null if the draggable is disabled
dragHandleProps: ?DragHandleProps,
|};
</code></pre>
<p><code>innerRef</code>:为了使<code>Draggable</code>正确运行,必须将<code>innerRef</code>函数绑定到ReactElement,希望将其视为<code>Draggable</code>节点。这样做是为了避免使用<code>ReactDOM</code>查找DOM节点。<br>
<code>draggableProps</code>:这是一个包含数据属性和内联样式的对象。此对象需要应用于将<code>innerRef</code>应用于的同一节点。它控制可拖动控件在拖动和不拖动时的移动。可添加自己的样式到DraggableProps-style, <strong>但请不要删除或替换任何属性</strong><br>
<code>draggableProps</code>:这是用来拖动整个<code>Draggable</code>的。这个节点通常与<code>Draggable</code>相同,但有时也可能是<code>Draggable</code>的子节点。拖柄道具需要应用到您想要作为拖柄的节点。这是一些需要应用到<code>Draggable</code>节点的道具。最简单的方法是将道具分散到可拖动节点上({…provider.draghandleprops})。但是,如果还需要回复他们,你给这些道具打补丁。当isDragDisabled被设置为true时,DragHandleProps将为null。</p>
<h6 id="22-子函数的snapshotdraggablestatesnapshot">2.2 子函数的Snapshot(DraggableStateSnapshot)</h6>
<pre><code>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,
|};
</code></pre>
<p>示例2:</p>
<pre><code><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>
</code></pre>
<h6 id="3-droppable">3. Droppable</h6>
<blockquote>
<p><code>Droppable</code> components can be dropped on by a <code>Draggable</code>. They also contain <code>Draggable</code>s. A <code>Draggable</code> must be contained within a <code>Droppable</code>.</p>
</blockquote>
<p>官方的意思是在拖拽的组件需要被包含在<code><Drppable/></code>。拖拽的容器 <code><Draggable /></code>也会包含在<code><Drppable/></code><br>
示例3</p>
<pre><code>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>;
</code></pre>
<p>接下来看一下Droppable props</p>
<pre><code>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';
</code></pre>
<p>参数说明:<br>
<code>droppableId</code>:一个需要 <code>DroppableId(string)</code>唯一标识该应用程序的可投入程序. 请不要更改此 Props , <strong>特别是在拖动时</strong>.<br>
<code>type</code>: 可选的<code> TypeId(string)</code>可以用来简单地接受一类<code>Draggable</code>. 例如,如果您使用该类型PERSON那么它只会允许Draggable类型的PERSON放下自己. Draggable类型的TASK将无法被放在Droppable与类型PERSON上. 如果不提供type,它将被设置为'DEFAULT'. 目前来说Draggable的type在Droppable之内 一定是一样. 如果有一个有效的用例,这个限制在将来可能会放松.</p>
<h6 id="31-子函数render-propsfunction-as-child">3.1 子函数(render Props/function as child)</h6>
<p><code>Droppable</code>的React子节点必须是返回react元素的函数。</p>
<pre><code><Droppable droppableId="droppable-1">
{(provided, snapshot) => ({
/*...*/
})}
</Droppable>
</code></pre>
<p>该函数有两个参数<br>
<strong><code>proviede: (DroppableProvided)</code></strong></p>
<pre><code>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,
|};
</code></pre>
<p>参数说明<br>
<code>provided.innerRef</code> : 为了使<code>droppable</code>正确运行,必须绑定所提供的。<code>innerRef</code>指向<code>ReactElement</code>中尽可能高的DOM节点。这样是为了避免使用<code>ReactDOM</code>查找DOM节点。<br>
<code>provided.placeholder</code> :用于在拖动过程中根据需要在<code>< Droppable /></code>中创建空格。当用户拖动非主列表的列表时,需要此空间。请确保将占位符放在您提供ref的组件中。我们需要增加本身的大小。<br>
<code>provided.droppableProps (DroppableProps) </code>:这是一个包含需要应用于可删除元素的属性的对象。它需要应用到与应用<code>provided.innerRef</code>相同的元素。它目前包含用于样式化和查找的数据属性。<br>
示例3.1</p>
<pre><code><Droppable droppableId="droppable-1">
{(provided, snapshot) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
Good to go
{provided.placeholder}
</div>
)}
</Droppable>
</code></pre>
<p><strong><code>snapshot: (DroppableStateSnapshot)</code></strong></p>
<pre><code>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,
|};
</code></pre>
<p><em><strong>注意:</strong></em></p>
<ul>
<li>Droppable 可以作为<code>Draggable</code>和<code>DragDropContext</code>的子组件。</li>
<li>Draggable 必须包含在<code><Droppable/></code> 中,即<code><Draggable /></code>,只能作为<code><Droppable /></code> 的子组件</li>
</ul>
</div>
<div id="MySignature" role="contentinfo">
<p>本文来自博客园,作者:前端加油站,转载请注明原文链接:https://www.cnblogs.com/bllx/p/17912245.html</p><br><br>
来源:https://www.cnblogs.com/bllx/p/17912245.html
頁:
[1]