react中实现拖拽排序react-dnd

2023-10-27

dnd文档

在这里插入图片描述

html 拖拽排序

import React, { useState, useRef } from 'react';
import { cloneDeep } from 'lodash';
import styles from './index.less';

const defaultList = [
    {
        id: 1,
        name: '11',
    },
    {
        id: 2,
        name: '22',
    },
];

export default ({ children = '', arr = [] }) => {
    const [list, setList] = useState([...defaultList]);
    const startRef = useRef(null);
    const changePosition = (dragIndex, hoverIndex) => {
        const data = cloneDeep(list);
        const temp = data[dragIndex];
        // 交换位置
        data[dragIndex] = data[hoverIndex];
        data[hoverIndex] = temp;
        setList(data);
    };
    const onDragStart = index => {
        // console.log('onDragStart', index);
        startRef.current = index;
    };
    const onDragEnd = (e, index) => {
        e.preventDefault();
    };
    const onDragOver = (e, index) => {
        e.preventDefault();
    };
    const onDragEnter = (e, hoverIndex) => {
        e.preventDefault();
        if (startRef.current === hoverIndex) {
            return;
        }
        startRef.current = hoverIndex; // 将当前当前移动到Box的index赋值给当前拖动的box,不然会出现两个盒子疯狂抖动!
        changePosition(startRef.current, hoverIndex);
        // console.log('onDragEnd', hoverIndex, '排序');
    };
    return (
        <div className={styles.list_container}>
            {list.map((item, index) => {
                return (
                    <div
                        className={styles.list_item}
                        draggable
                        key={item?.id}
                        onDragStart={$event => onDragStart(index)}
                        onDragEnd={$event => onDragEnd($event, index)}
                        onDragEnter={$event => onDragEnter($event, index)}
                        onDragOver={$event => onDragOver($event, index)}
                    >
                        {item.name}
                        {/* {children} */}
                    </div>
                );
            })}
        </div>
    );
};

拖拽组件封装

import React, { useRef } from 'react';
import { useDrop, useDrag } from 'react-dnd';
import styles from './index.less';
// 拖拽排序
export default ({ id = '', index = '', changePosition = () => {}, className = {}, children, rowKey = '' }) => {
    const ref = useRef(null);
    // 因为没有定义收集函数,所以返回值数组第一项不要
    const [, drop] = useDrop({
        accept: 'DragDropBox', // 只对useDrag的type的值为DragDropBox时才做出反应
        hover: (item, monitor) => {
            // 这里用节流可能会导致拖动排序不灵敏
            if (!ref.current) return;
            const dragIndex = item.index;
            const hoverIndex = index;
            if (dragIndex === hoverIndex) return; // 如果回到自己的坑,那就什么都不做
            changePosition(dragIndex, hoverIndex); // 调用传入的方法完成交换
            item.index = hoverIndex; // 将当前当前移动到Box的index赋值给当前拖动的box,不然会出现两个盒子疯狂抖动!
        },
    });

    const [{ isDragging }, drag] = useDrag({
        item: {
            type: 'DragDropBox',
            id,
            index,
        },
        collect: monitor => ({
            isDragging: monitor.isDragging(), // css样式需要
        }),
    });

    return (
        // ref 这样处理可以使得这个组件既可以被拖动也可以接受拖动
        <div ref={drag(drop(ref))} style={{ opacity: isDragging ? 0.5 : 1 }} className={className.dragBox}>
            <span key={rowKey} className={styles.reviewer}>
                {children}
            </span>
        </div>
    );
};


使用组件

import React from 'react';
import { DndProvider } from 'react-dnd';
import { useSelector } from 'umi';
import { cloneDeep } from 'lodash';
import HTML5Backend from 'react-dnd-html5-backend';
import ReactDndDragSort from '@/components/ReactDndDragSort';
import styles from './index.less';

export default ({ currentModel, dispatch }) => {
    const { reviewerList = [] } = useSelector(state => state[currentModel]);

    const changePosition = (dragIndex, hoverIndex) => {
        const data = cloneDeep(reviewerList);
        const temp = data[dragIndex];
        // 交换位置
        data[dragIndex] = data[hoverIndex];
        data[hoverIndex] = temp;
        // setBoxList(data);
        dispatch({
            type: `${currentModel}/overrideStateProps`,
            payload: {
                reviewerList: data,
            },
        });
    };
    return (
        <>
            <div className={styles.reviewerContainer}>
                <DndProvider backend={HTML5Backend}>
                    {reviewerList?.length ? (
                        <div style={{ display: 'flex' }}>
                            {reviewerList.map((item, index) => {
                                return (
                                    <ReactDndDragSort
                                        rowKey={item?.id}
                                        index={index}
                                        id={item?.id}
                                        changePosition={changePosition}
                                    >
                                        <span key={item?.id} className={styles.reviewer}>
                                            <div className={styles.reviewerImg}>
                                                <span
                                                    className="saas saas-failure1"
                                                    onClick={() => {
                                                        const listFilter = reviewerList.filter(
                                                            (_, itemIndex) => itemIndex !== index,
                                                        );
                                                        dispatch({
                                                            type: `${currentModel}/overrideStateProps`,
                                                            payload: {
                                                                reviewerList: listFilter,
                                                            },
                                                        });
                                                    }}
                                                />
                                            </div>
                                            <div className={styles.reviewerTxt}>{item.name}</div>
                                        </span>
                                    </ReactDndDragSort>
                                );
                            })}
                        </div>
                    ) : null}
                </DndProvider>
            </div>
        </>
    );
};


ts 版本

import React, { useRef } from "react";
import { useDrop, useDrag } from "react-dnd";
import "./index.less";
// dnd拖拽排序
export default (props: any) => {
  const {
    id = "",
    index = "",
    changePosition = () => {},
    className = "",
    children,
    rowKey = "",
  } = props;
  const ref: any = useRef(null);
  // 因为没有定义收集函数,所以返回值数组第一项不要
  const [, drop] = useDrop({
    accept: "DragDropBox", // 只对useDrag的type的值为DragDropBox时才做出反应
    hover: (item: any, monitor: any) => {
      // 这里用节流可能会导致拖动排序不灵敏
      if (!ref.current) return;
      const dragIndex = item.index;
      const hoverIndex = index;
      if (dragIndex === hoverIndex) return; // 如果回到自己的坑,那就什么都不做
      changePosition(dragIndex, hoverIndex); // 调用传入的方法完成交换
      item.index = hoverIndex; // 将当前当前移动到Box的index赋值给当前拖动的box,不然会出现两个盒子疯狂抖动!
    },
  });

  const [{ isDragging }, drag] = useDrag(() => ({
    type: "DragDropBox",
    item: { id, type: "DragDropBox", index },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(), // css样式需要
    }),
  }));
  const changeRef = drag(drop(ref));

  return (
    // ref 这样处理可以使得这个组件既可以被拖动也可以接受拖动
    <div
      //@ts-ignore
      ref={changeRef}
      style={{ opacity: isDragging ? 0.5 : 1 }}
      className="dragBox"
    >
      <span key={rowKey} className={className}>
        {children}
      </span>
    </div>
  );
};

ts使用

import React, { useState } from "react";
import { DndProvider } from "react-dnd";
import { useSelector } from "react-redux";
//@ts-ignore
import { cloneDeep } from "lodash";
import { HTML5Backend } from "react-dnd-html5-backend";
import ReactDndDragSort from "@/components/ReactDndDragSort";
import "./index.less";
console.log("HTML5Backend", HTML5Backend);

export default () => {
  const dList = [
    {
      id: 99,
      name: "组1",
    },
    {
      id: 22,
      name: "组2",
    },
  ];
  const [reviewerList, setReviewerList] = useState(dList);

  const changePosition = (dragIndex: any, hoverIndex: any) => {
    const data = cloneDeep(reviewerList);
    const temp = data[dragIndex];
    // 交换位置
    data[dragIndex] = data[hoverIndex];
    data[hoverIndex] = temp;
    console.log("交换完成---", data);
    setReviewerList(data);
  };
  return (
    <>
      <div className="reviewerContainer">
        <DndProvider backend={HTML5Backend}>
          {reviewerList?.length ? (
            <div>
              {reviewerList.map((item: any, index: any) => {
                return (
                  <ReactDndDragSort
                    rowKey={item?.id}
                    index={index}
                    id={item?.id}
                    changePosition={changePosition}
                  >
                    <div key={item?.id} className="reviewer">
                      <div className="reviewerTxt">{item.name}</div>
                    </div>
                  </ReactDndDragSort>
                );
              })}
            </div>
          ) : null}
        </DndProvider>
      </div>
    </>
  );
};

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

react中实现拖拽排序react-dnd 的相关文章

  • 如何将值发布到输入框中?

    Intro I would like to get the current time after clicking at click and POST the value into input text box Note 假设包含引导样式表
  • 获取被调用的 javascript 文件的查询字符串

    是否可以在调用的 javascript 文件上使用 javascript 获取查询参数 如下所示 in html in file js console log this location query 这是否可能以某种方式实现 或者我必须使用
  • Javascript 进程是否有多个执行线程?

    背景 我正在创建一个 地址簿 类型的应用程序 有很多条目需要加载 一个想法是首先加载一小部分条目 让用户开始 然后将剩余条目排队 优先考虑用户单击的条目 例如 如果他们单击以 X 开头的名称 请先加载这些名称 然后再处理队列的其余部分 这个
  • 检测 Webkit/Chrome 中 HTML5 数字控件更改的事件?

    HTML5 为我们提供了一些新的输入元素 例如
  • onClick 处理程序在每个渲染周期触发

    我有这样的默认状态 this state selectedTab tab1 then 我的渲染方法是这样的 render const selectedTab this state return li tab1 li li tab2 li d
  • Apache Thrift Java-Javascript 通信

    我正在编写一个基于 Apache Thrift 的 Java 服务器 它将从 Javascript 客户端接收数据 我已经完成了 Java 服务器 但问题是我可以获得 Javascript 客户端的工作示例 我无法找到一个好的示例 构建文档
  • 如何通过setTimeout函数定期打印数字?

    var i 0 function counter for i i lt 100 i setTimeout gt console log i 2000 counter 我想以 2 秒的间隔打印 i 但它立即打印 每次打印调用只需要几微秒 为什
  • Jest - 测试使用react-router的组件

    我正在测试一个呈现具有以下 contextTypes 的子组件的组件 Component contextTypes router PropTypes object isRequired 我对笑话完全陌生 但来自摩卡 酶我从未遇到过这个问题
  • 从 Context Provider 重定向 React Router

    我是 React Router 的新手 并尝试使用新的 Conext API 从提供程序内部进行重定向 基本上我的提供者看起来像这样 AuthContext js class AuthProvider extends React Compo
  • Angular 4 Http POST 不起作用

    我希望每个人都做得很好 我最近开始使用 Angular 4 4 我一直在尝试将数据发布到我的 api 服务器 但不幸的是它不起作用 我花了大约两天的时间 但仍然没有成功 甚至已经尝试过 6 7 篇文章角 io https angular i
  • Angular2:动态同步http请求

    Goal 发出一系列同步 http 请求并能够将它们作为一个可观察流进行订阅 示例 不工作 let query arr test1 test2 test3 function make request query arr if query a
  • 从链接打开本地文件夹

    如何通过单击任何链接打开本地文件夹视图 我尝试了很多选择 例如 a href Open folder a or a Open folder a or a Open folder a 解决方案 启动可下载链接 以下内容适用于所有浏览器 但一如
  • 如何在React中动态分配属性?

    这是一个有两个参数的函数 我要创建的标签的名称 具有以下属性的对象 Using React 我创建一个组件并将该元素渲染到 DOM 问题是我想向元素添加属性 但它不允许循环在元素内设置属性 var Element function elem
  • 如何从 CSS 选择器中提取类名?

    故事 我目前正在构建一个 ESLint 规则 以警告在 CSS 选择器定位器中使用引导布局导向和角度技术类 目前我在字符串方法中使用简单的子字符串 for var i 0 i lt prohibitedClasses length i if
  • Firebase + Node.js:错误:找不到 XMLHttpRequest 兼容性库

    Firebase Node js On iOS 安装的 Node js npm 安装 firebase save 节点测试 js 其中 test js 是一个非常简单的连接到 Firebase 的脚本 var firebase requir
  • 当php脚本通过ajax运行时显示进度条

    我有一个通过 ajax 向服务器提交值的表单
  • onPress 方法中箭头函数与普通函数的行为

    正在学习 Native React 并学习更多关于 javascript 的知识 所以我仍然不明白它的行为的很多事情 我使用 TouchableOpacity 及其 onPress 属性创建了一个按钮组件 为了让它工作 我必须发送我想要执行
  • 如何在 TypeScript 中使用 navigation.replace ?

    我试图在我的代码中使用它 const navigation useNavigation navigation replace AllFriends 但我不断收到错误消息 Property replace does not exist on
  • Three.js点击单个粒子

    In this example http jsfiddle net agqq96bq 2 您可以看到 2 个可点击的粒子 但它们都受到点击的影响 另外 我只想检测粒子上的点击 而不将它们过滤出场景 像这儿 if intersects len
  • 为什么 JavaScript 中是 [1,2] + [3,4] = "1,23,4" ?

    我想将一个数组的元素添加到另一个数组中 所以我尝试了以下方法 1 2 3 4 它的回应是 1 23 4 到底是怎么回事 The 操作员没有为数组定义 发生的事情是 JavaScript将数组转换为字符串并将它们连接起来 Update 由于这

随机推荐

  • linux内核中的驱动查找

    一 使用make menuconfig 可以查看具体编译了哪些驱动 在内核根目录下输入sudo make menuconfig 进入界面后 选择Device Drives 具体界面如下 进去后可以看到很多驱动名字 以I2C为例 选中后选择h
  • Uva 489 Hangman Judge

    本题不难 但是我花了一个学期才AC 找到原因后想狠狠地揍自己一顿 原来是输出的一个单词拼错了 一直在解题思路和细节上找问题的我还曾吐槽这是什么脑残游戏 以后需细心 include
  • qt .pro文件配置

    模板变量TEMPLATE TEMPLATE app 表示是可执行应用程序 TEMPLATE lib 表示是库 TEMPLATE subdirs 创建一个可进入特定目录并为一个项目文件生成 指定项目中使用Qt的模块 默认情况下 QT包含cor
  • 神经网络 — 激活函数

    生物神经网络是一个复杂的网络结构 人工神经网络是借鉴生物神经网络的最基本特征 利用神经元和神经元之间的连接 从而构成的一种数学模型 生物神经元能够接收其他多个神经元的输入 当这些输入累计超过一定的阈值时 这个神经元就会被激活 产生输出 在设
  • Nginx反向代理location与proxy_pass配置规则总结

    一 location配置规则 1 匹配模式及顺序举例 location uri 开头表示精确匹配 只有完全匹配上才能生效 location uri 开头对 URL 路径进行前缀匹配 并且在正则之前 location pattern 开头表示
  • [深度学习]Semantic Segmentation语义分割之UNet(2)

    论文全称 U Net Convolutional Networks for Biomedical Image Segmentation 论文地址 https arxiv org pdf 1505 04597v1 pdf 论文代码 https
  • 用Flutter写一个单例

    在Flutter中创建单例可以使用Dart语言中的静态变量和工厂方法的组合来实现 下面是一个示例代码 class MySingleton 静态变量 static final MySingleton singleton MySingleton
  • PL/SQL 怎么判断两个结果集是否相等

    数据库服务器 Oracle 现在有两个结果集 A1 Cause Rate UEG 2000 GYU 1900 NBU 2900 CET 3000 A2 Cause Rate UEG 2000 GYU 1900 NBU 2900 CET 30
  • png lib error bad parameters to zlib

    目录 1 问题描述 2 问题分析 3 解决方案 3 1 解决方法一 3 2 解决方法二 1 问题描述 在 Linux ubuntu 编译 PNG 库时 出现了 png lib error bad parameters to zlib 错误
  • Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用

    转载请注明本文出自xiaanming的博客 http blog csdn net xiaanming article details 26810303 请尊重他人的辛勤劳动成果 谢谢 大家好 差不多两个来月没有写文章了 前段时间也是在忙换工
  • Elasticsearch 部署以及插件安装(win7)

    Elasticsearch 部署以及插件安装 win7 一 安装版本 找到对应版本 我使用的是2 3 5版本 安装包下载地址https www elastic co downloads past releases elasticsearch
  • LEAKAGE IN NANOMETER CMOS TECHNOLOGIES

    纳米CMOS管技术中的漏电流 https link springer com book 10 1007 0 387 28133 9
  • ORA-00933: SQL 命令未正确结束

    java sql SQLSyntaxErrorException ORA 00933 SQL 命令未正确结束 在数据库中语句运行完全没问题 但是在编程的时候却报这样的错误 控制台看似报一大堆异常原因可能是 1 你没逗号可能没写够 仔细检查S
  • 获取字符串长度的函数sizeof()、strlen()、length()、size()详解和区别

    在C 中计算长度的函数有四种 它们分别是sizeof size strlen str length 一 sizeof 和strlen 两者区别 1 sizeof操作符的结果类型是size t 该类型保证能容纳实现所建立的最大对象的字节大小
  • jQuery 获取 input:file 文件路径( Firefox for Ubuntu )

    在写一个小项目的时候遇到了一个问题 通过jquery获取选择的文件的路径 最开始选择的是通过 val 获取路径 但是后来发现获取到的路径有问题原始路径是 home onemue 案例 表情上传 前端 pic png获取到的路径是C fake
  • C++之萃取技术

    自从C 中引入了template后 以泛型技术为中心的设计得到了长足的进步 STL就是这个阶段杰出的产物 STL的目标就是要把数据和算法分开 分别对其进行设计 之后通过一种名为iterator的东西 把这二者再粘接到一起 设计模式中 关于i
  • 消息队列之基础知识(一)

    来自公众号 灰子学技术 欢迎关注 笔者最近在看消息队列 顺便做了整理 在学习这个知识点之前 笔者问了自己下面几个问题 什么是消息队列 为什么我们需要消息队列 消息队列有什么用 常用的消息队列有那些 以下内容 读者便从这几个方面开始说起 一
  • windows7下解决caffe check failed registry.count(type) == 1(0 vs. 1) unknown layer type问题

    在Windows7下调用vs2013生成的Caffe静态库时经常会提示Check failed registry count type 1 0 vs 1 Unknown layer type的错误 如下图 这里参考网上资料汇总了几种解决方法
  • 安卓音乐播放器--侧边栏

    侧边栏学习 参考资料 http www chinatarena com Html adpeixun 201307 5251 html 还有一个参考的代码 最后自己的理解是 在scrollView中添加两个水平的视图 musicListLay
  • react中实现拖拽排序react-dnd

    dnd文档 html 拖拽排序 import React useState useRef from react import cloneDeep from lodash import styles from index less const