使用react-beautiful-dnd实现列表间拖拽排序功能

林英朗
2023-12-01

基本概念
DragDropContext:用于包装拖拽根组件,构建一个可以拖拽的范围,Draggable和Droppable都需要包裹在DragDropContext内,不支持嵌套
Droppable:用于包装接收拖拽元素的组件,使被拖动元素可以放置该区域
Draggalbe:用于包装你需要拖动的组件,使组件能够被拖拽

使用方法

1、在项目 package.json 添加相应版本号
        "react-beautiful-dnd": "^10.0.3"

2、把你想能够拖放的代码放到DragDropContext中

import React from 'react';
import {DragDropContext} from 'react-beautiful-dnd';
 
class App extends React.Component {
  //在捕获之前
  onBeforeCapture = () => {
    /*...*/
  };
  //在拖动开始之前
  onBeforeDragStart = () => {
    /*...*/
  };
  //在拖动开始时
  onDragStart = () => {
    /*...*/
  };
  //在拖动变化时
  onDragUpdate = () => {
    /*...*/
  };
  //在拖动结束时
  onDragEnd = result => {
   console.log(result);
  };
 
  render() {
    return (
      <DragDropContext
        onBeforeCapture={this.onBeforeCapture}
        onBeforeDragStart={this.onBeforeDragStart}
        onDragStart={this.onDragStart}
        onDragUpdate={this.onDragUpdate}
        onDragEnd={this.onDragEnd}
      >
        <div>Hello world</div>
      </DragDropContext>
    );
  }
}
export default App;

3、确定可放置区域Dropppable

import React from 'react';
import {DragDropContext,Droppable} from 'react-beautiful-dnd';
 
class App extends React.Component {
  // ...
  getDroppableStyle = snapshot => ({
    //backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey';
  });
  render() {
    return (
      <DragDropContext
		onBeforeCapture={this.onBeforeCapture}
        onBeforeDragStart={this.onBeforeDragStart}
        onDragStart={this.onDragStart}
        onDragUpdate={this.onDragUpdate}
        onDragEnd={this.onDragEnd}
      >
        <Droppable key = "droppable-1" droppableId="droppable-1" type="PERSON" isDropDisabled = {false}>
          {(provided, snapshot) => (
            <div
              ref={provided.innerRef}
              style={this.getDroppableStyle(snapshot)}
              {...provided.droppableProps}
            >
              <h2>I am a droppable!</h2>
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    );
  }
}
export default App;

droppableId:必要的参数(字符串),用于唯一标识,不要更改此ID,特别是在拖动时
type: 可用于仅接受指定的类。例如:如果您使用type=“person”,那么它将只允许将类型“person”的放到自身上。type=‘task’的将不能被拖放到type为‘person’的上。如果没有提供类型,它将被设置为“DEFAULT”。
direction : 项目流动的方向。选项有 "vertical" (默认)和 "horizontal"。
isDropDisabled:用来确定该区域是否可放置元素,默认为false。true:不可放置,false:可以放置
其下钩子函数参数使用说明:
    provided.innerRef:为了使droppable正确运行,您必须绑定所提供的。innerRef指向ReactElement中尽可能高的DOM节点。这样做是为了避免使用ReactDOM查找DOM节点。
    provided.droppableProps:这是一个包含需要应用于可删除元素的属性的对象。它需要应用到与应用provided.innerRef相同的元素。它目前包含用于样式化和查找的数据属性。
    provided.placeholder: 用于在拖动过程中根据需要在< Droppable />中创建空格。当用户拖动非主列表的列表时,需要此空间。请确保将占位符放在您提供ref的组件中。我们需要增加本身的大小。
    snapshot:当前拖动状态,可以用来在被拖动时改变Droppable的外观,snapshot.isDraggingOver:是否拖动结束

4、在Dropppable区域使用Draggable包裹拖拽元素

import React from 'react';
import {DragDropContext,Droppable,Draggable} from 'react-beautiful-dnd';
 
class App extends React.Component {
  // ...
  
  render() {
    return (
      <DragDropContext
        onBeforeCapture={this.onBeforeCapture}
        onBeforeDragStart={this.onBeforeDragStart}
        onDragStart={this.onDragStart}
        onDragUpdate={this.onDragUpdate}
        onDragEnd={this.onDragEnd}
      >
		 <Droppable key = "droppable-1" droppableId="droppable-1" type="PERSON" isDropDisabled = {false}>
          {(provided, snapshot) => (
            <div
              ref={provided.innerRef}
              style={this.getDroppableStyle(snapshot)}
              {...provided.droppableProps}
            >
               <Draggable key = "draggable-1" draggableId = "draggable-1" index={0} isDragDisabled = {false}>
                {(provided, snapshot) => (
                    <div
                      ref={provided.innerRef}
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                    >
                      <h4>My draggable</h4>
                    </div>
                )}
              </Draggable>
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    );
  }
}
export default App;

<Draggable /> 必须始终包含在<Droppable /> 中
droppableId:必要的参数(字符串),用于唯一标识,不要更改此ID特别是在拖动时
index:number类型,必须唯一,必须连续
isDragDisabled:用来确定该元素是否可以被拖动,true:不可拖动,false:可以拖动

5、拖拽结束时,改变源数据

onDragEnd = result => {
  const {source, destination, draggableId} = result;
  //不在拖动范围内则视为没有进行拖动操作
  if (!destination) {
    return;
  }
  //将拖拽元素从源数组中删除,再插入到目标数组中
  // let now_userList = Array.from(this.state.userList);
  // const [removed] = now_userList.splice(source.index,1);
  // now_userList.splice(destination.index,0,removed);
  // //更新数据源
  // this.setState({
  //   userList:now_userList
  // });
}

 类似资料: