zoukankan      html  css  js  c++  java
  • react 拖拽组件 自由拖拽,垂直水平拖拽

    react拖拽组件

    最近忙着公司后台系统开发,因为需求用到了拖拽.给大家安利几个好用的拖拽组件!

    1.第一个拖拽组件 antd的Tree组件

    这个拖拽组件经常用于层级关系的拖拽组件 可以动态的增删改 (排序,添加子层级~父层级,修改等).
    antd-Tree拖拽图片
    import React, { useEffect, useState } from "react"
    import { Tree, message } from 'antd'; //导入antd 的Tree组件
    
    export default function App() {
        const [data, setData] = useState([])
        useEffect(() => {
            if (data.length === 0) {
                //初始化数据
                setData([{ title: "组1", key: 1 },
                { title: "组2", key: 2, children: [{ title: "子组1", key: 6 }, { title: "子组2", key: 7 }, { title: "子组3", key: 9 }] },
                { title: "组3", key: 3 },
                { title: "组4", key: 4 }])
            }
        }, [data])
        //完成拖拽
        const onDrop = info => {
    
            /**
             *  这里是判断 拖拽之后的动作是否允许存在跨级拖拽交换位置等等...
             *  若需要判断可以取消注释
             */
            // let nodePosArr = info.node.pos.split('-')
            // let dropPosArr = info.dragNode.pos.split('-')
            // if (dropPosArr.length === nodePosArr.length && nodePosArr[1] !== dropPosArr[1]) return message.error("不可拖入其他类别")
            // if (nodePosArr.length !== dropPosArr.length) return message.error("列表禁止跨级拖拽")
            // if (!info.dropToGap) return message.error("同级列表只能互换顺序")
    
            const dropKey = info.node.props.eventKey;
            const dragKey = info.dragNode.props.eventKey;
            const dropPos = info.node.props.pos.split('-');
            const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
    
            const loop = (data, key, callback) => {
                for (let i = 0; i < data.length; i++) {
                    if (data[i].key === key) {
                        return callback(data[i], i, data);
                    }
                    if (data[i].children) {
                        loop(data[i].children, key, callback);
                    }
                }
            };
            const changeData = [...data];
    
            // Find dragObject
            let dragObj;
            loop(changeData, dragKey, (item, index, arr) => {
                arr.splice(index, 1);
                dragObj = item;
            });
    
            if (!info.dropToGap) {
                // Drop on the content
                loop(data, dropKey, item => {
                    item.children = item.children || [];
                    // where to insert 示例添加到尾部,可以是随意位置
                    item.children.push(dragObj);
                });
            } else if (
                (info.node.props.children || []).length > 0 && // Has children
                info.node.props.expanded && // Is expanded
                dropPosition === 1 // On the bottom gap
            ) {
                loop(data, dropKey, item => {
                    item.children = item.children || [];
                    // where to insert 示例添加到头部,可以是随意位置
                    item.children.unshift(dragObj);
                });
            } else {
                let ar;
                let i;
                loop(data, dropKey, (item, index, arr) => {
                    ar = arr;
                    i = index;
                });
                if (dropPosition === -1) {
                    ar.splice(i, 0, dragObj);
                } else {
                    ar.splice(i + 1, 0, dragObj);
                }
            }
            //changeData就是拖拽结束后改变的数据格式, 需要在这里重新赋值 即可显示最新拖拽之后的结果
            setData(changeData)
        };
        /**
         * 
         * @param {Array} selectedKeys  选中的key 数组存放,单多选
         * @param {Node} e 被选择中的node信息,可以拿到 数据源, 层级关系等...
         */
        //完成选择
        const onSelect = (selectedKeys, e) => {
            console.log(selectedKeys, e);
        }
        return <>
            <Tree
                draggable //是否可以拖拽
                blockNode //是否节点占据一行	
                showLine  //	是否展示连接线
                treeData={data} //数据源 格式 Array 每项的数据格式Object { key:..., title:...,... }
                onDrop={onDrop} //拖拽结束后触发的回调函数
                onSelect={onSelect} // 选中某一级的回调函数
            />
        </>
    }
    

      

    2. 第二个拖放组件 react-beautiful-dnd

    这个拖拽组件用于列表拖拽,只可以水平,垂直拖拽.拖拽的UI非常不错, 可以动态增删列表
    react-beautiful-dnd拖拽图片
    import React, { useEffect, useState } from "react"
    import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
    
    //每一项的样式
    const getItemStyle = () => ({
        background: "white",
        height: 50,
        border: "1px solid red",
         "100%",
        margin: "0 0 20px 0"
    })
    
    // 重新记录数组顺序
    const reorder = (list, startIndex, endIndex) => {
        const result = Array.from(list);
        //删除并记录 删除元素
        const [removed] = result.splice(startIndex, 1);
        //将原来的元素添加进数组
        result.splice(endIndex, 0, removed);
        return result;
    };
    
    
    export default function App() {
        const [data, setData] = useState([])
        useEffect(() => {
            if (data.length === 0) {
                //初始化数据
                const newData = Array.from({ length: 5 }, (item, index) => ({ key: "key" + index, content: "item" + index }))
                setData(newData)
            }
        }, [data])
    
        //拖拽结束
        const onDragEnd = (result) => {
            if (!result.destination) {
                return;
            }
            //获取拖拽后的数据 重新赋值
            const newData = reorder(data, result.source.index, result.destination.index)
            setData(newData)
        }
        return <DragDropContext onDragEnd={onDragEnd}>
            {/* direction代表拖拽方向  默认垂直方向  水平方向:horizontal */}
            <Droppable droppableId="droppable">
                {(provided, snapshot) => (
                    //这里是拖拽容器 在这里设置容器的宽高等等...
                    <div
                        {...provided.droppableProps}
                        ref={provided.innerRef}
                        style={{
                             800,
                            padding: 10
                        }}
                    >
                        {/* 这里放置所需要拖拽的组件,必须要被 Draggable 包裹 */}
                        {
                            data.map((item, index) => (
                                <Draggable
                                    index={index}
                                    key={item.key}
                                    draggableId={item.key}
                                >
                                    {(provided, snapshot) => (
                                        //在这里写你的拖拽组件的样式 dom 等等...
                                        <div
                                            ref={provided.innerRef}
                                            {...provided.draggableProps}
                                            {...provided.dragHandleProps}
                                            style={{ ...getItemStyle(), ...provided.draggableProps.style }}
                                        >
                                            {item.content}
                                        </div>
                                    )}
    
                                </Draggable>
                            ))
                        }
                        {/* 这个不能少 */}
                        {provided.placeholder}
                    </div>
                )}
            </Droppable>
        </DragDropContext>
    }
    

      

    3.第三个拖拽组件 react-draggable-tags

    一个轻量级的拖拽排序组件。该组件封装了一系列拖拽功能,可以灵活使用,也未提供任何样式,完全由你来控制(不一定是“tag”,你可以放入任意组件来拖拽排序)。支持移动端。
    react-draggable-tags拖拽图片
    import React, { useEffect, useState } from "react";
    import { DraggableArea } from 'react-draggable-tags';
    
    
    export default function App() {
        const [data, setData] = useState([])
        useEffect(() => {
            if (data.length === 0) {
                setData([
                    { id: 1, content: 'apple' }, { id: 2, content: 'olive' }, { id: 3, content: 'banana' },
                    { id: 4, content: 'lemon' }, { id: 5, content: 'orange' }, { id: 6, content: 'grape' },
                    { id: 7, content: 'strawberry' }, { id: 8, content: 'cherry' }, { id: 9, content: 'peach' }
                ])
            }
        }, [data])
        //拖拽结束后触发的函数,返回已经改变的data
        const onChange = (tags) => {
            console.log(tags);
        }
        //渲染每项
        const itemRender = ({ tag, index }) => {
            return <div className="tag">
                {tag.content}
            </div>
        }
        return <div className="Simple">
            <DraggableArea
                tags={data}
                render={itemRender}
                onChange={onChange}
            />
        </div>
    }
    

      

     
  • 相关阅读:
    MongoDB(13)- 查询操作返回指定的字段
    MongoDB(12)- 查询嵌入文档的数组
    MongoDB(11)- 查询数组
    MongoDB(10)- 查询嵌套文档
    MongoDB(9)- 文档查询操作之 find() 的简单入门
    MongoDB(8)- 文档删除操作
    MongoDB(7)- 文档插入操作
    MongoDB(6)- BSON 数据类型
    MongoDB(5)- Document 文档相关
    MongoDB(4)- Collection 集合相关
  • 原文地址:https://www.cnblogs.com/kongyijilafumi/p/13734668.html
Copyright © 2011-2022 走看看