IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> react中实现一个简单的拖拽排序react-dnd -> 正文阅读

[JavaScript知识库]react中实现一个简单的拖拽排序react-dnd

dnd文档

在这里插入图片描述

import React, { useEffect, useRef, useState } from 'react';
import { DndProvider } from 'react-dnd';
import { Form, Card } from 'antd';
import { useSelector } from 'umi';
import { cloneDeep } from 'lodash';
import HTML5Backend from 'react-dnd-html5-backend';
import styles from './index.less';
import ApprovePersonModel from './ApprovePersonModel';
import DragDropBox from './DragDropBox';
// 输入框最大字符数
export const INPUT_LENGTH_LIMIT = 50;
// 文本框最大字符数
export const TEXT_AREA_LENGTH_LIMIT = 500;

export default ({ currentModel, baseInfo, dispatch, type, change_reason }) => {
    const { adminList = [] } = useSelector(state => state[currentModel]);
    const [form] = Form.useForm();
    const [isModal, setIsModal] = useState(false);
    const { setFieldsValue } = form;
    const formRef = useRef(null);
    useEffect(() => {
        formRef.current = form;
    }, [form]);
    useEffect(() => {
        setFieldsValue({
            change_reason,
        });
    }, [change_reason, setFieldsValue]);
    useEffect(() => {
        dispatch({
            type: `${currentModel}/overrideStateProps`,
            payload: {
                otherForm: formRef,
            },
        });
    }, [dispatch, formRef, currentModel]);

    const approvePersonModelprops = {
        title: '新增审批人',
        currentModel,
        modalVisible: isModal,
        dispatch,
        dataList: adminList,
        limit: 5,
        handleOk: res => {
            dispatch({
                type: `${currentModel}/overrideStateProps`,
                payload: {
                    adminList: res?.adminList,
                },
            });
            setIsModal(false);
        },
        handleCancel: () => {
            setIsModal(false);
        },
        afterClose: () => {
            setIsModal(false);
        },
    };

    const changePosition = (dragIndex, hoverIndex) => {
        const data = cloneDeep(adminList);
        const temp = data[dragIndex];
        // 交换位置
        data[dragIndex] = data[hoverIndex];
        data[hoverIndex] = temp;
        // setBoxList(data);
        dispatch({
            type: `${currentModel}/overrideStateProps`,
            payload: {
                adminList: data,
            },
        });
    };
    return (
        <>
            <Card
                title={
                    <span className={styles.title}>
                        <i>*</i>审批
                    </span>
                }
                className={styles.card}
                bordered
                style={{ marginTop: 20 }}
            >
                <div className={styles.reviewerContainer}>
                    {adminList?.length && 0
                        ? adminList.map((ele, index) => {
                              return (
                                  <span key={ele?.id} className={styles.reviewer}>
                                      <div className={styles.reviewerImg}>
                                          <span
                                              className="saas saas-failure1"
                                              onClick={() => {
                                                  const listFilter = adminList.filter(
                                                      (_, itemIndex) => itemIndex !== index,
                                                  );
                                                  dispatch({
                                                      type: `${currentModel}/overrideStateProps`,
                                                      payload: {
                                                          adminList: listFilter,
                                                      },
                                                  });
                                              }}
                                          />
                                      </div>
                                      <div className={styles.reviewerTxt}>{ele.name}</div>
                                  </span>
                              );
                          })
                        : null}
                    <DndProvider backend={HTML5Backend}>
                        {adminList?.length ? (
                            <div style={{ display: 'flex' }}>
                                {adminList.map((item, index) => {
                                    return (
                                        <DragDropBox
                                            key={item?.id}
                                            index={index}
                                            id={item?.id}
                                            text={item?.text}
                                            itemInfo={item}
                                            changePosition={changePosition}
                                            handleClick={val => {
                                                const listFilter = adminList.filter(
                                                    (_, itemIndex) => itemIndex !== val,
                                                );
                                                dispatch({
                                                    type: `${currentModel}/overrideStateProps`,
                                                    payload: {
                                                        adminList: listFilter,
                                                    },
                                                });
                                            }}
                                        />
                                    );
                                })}
                            </div>
                        ) : null}
                    </DndProvider>
                    {adminList?.length < 5 ? (
                        <span
                            className={styles.createModal}
                            onClick={() => {
                                setIsModal(true);
                            }}
                        >
                            + <br />
                            新增
                        </span>
                    ) : null}
                </div>
            </Card>

            <ApprovePersonModel {...approvePersonModelprops} />
        </>
    );
};

import React, { useRef } from 'react';
import { useDrop, useDrag } from 'react-dnd';
import styles from './index.less';

export default ({
    id = '',
    text = '',
    index = '',
    changePosition = () => {},
    handleClick = () => {},
    className = {},
    itemInfo = {},
}) => {
    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,
            text,
        },
        collect: monitor => ({
            isDragging: monitor.isDragging(), // css样式需要
        }),
    });

    return (
        // ref 这样处理可以使得这个组件既可以被拖动也可以接受拖动
        <div ref={drag(drop(ref))} style={{ opacity: isDragging ? 0.5 : 1 }} className={className.dragBox}>
            <span key={itemInfo?.id} className={styles.reviewer}>
                <div className={styles.reviewerImg}>
                    <span className="saas saas-failure1" onClick={() => handleClick(index)} />
                </div>
                <div className={styles.reviewerTxt}>{itemInfo?.name}</div>
            </span>
        </div>
    );
};

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-25 08:01:50  更:2021-11-25 08:03:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 3:29:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码