在react中使用Dragula实现网页元素拖拽,嵌套拖拽

在react中使用Dragula实现网页元素拖拽,嵌套拖拽

 在开发一个react项目时,需要实现一个拖拽功能,而由于某些原因,react-dnd,react-beautiful-dnd等react拖拽组件无法被使用。于是我将目光放在了js拖拽库上,在实验了众多后,终于被我找到了dragula。它是我目前所见到的最为简单易用的拖拽库。

 github链接: https://github.com/bevacqua/dragula/

1.Dragula基本用法

 dragula的用法很简单,首先画出两个区域,并且将这两个区域的id分别命名div2,div3

  const data2=[{id:'1',name:'green'},{id:'2',name:'blue'},{id:'3',name:'red'}]
  const data3=[{id:'1',name:'cat'},{id:'2',name:'dog'},{id:'3',name:'bird'}]

    return (
        <div  className='dragulaPage'>
            <div id='div2' className='dragContainers'>
                {data2.map((data)=>(
                    <div  key={data.id} className='dragBlock' style={{border:`1px solid ${data.name}`}}>{data.name}</div>
                ))}
            </div>
            <div id='div3' className='dragContainers'>
                {data3.map((data)=>(
                    <div  key={data.id} style={{border:`1px solid yellow`}}>{data.name}</div>
                ))}
            </div>
        </div>
    );

在这里插入图片描述
接着调用dragula

import dragula from 'dragula';

const dragSet = dragula([document.getElementById('div2'),document.getElementById('div3')], {
            direction: 'horizontal',
      });

这样,位于div2和div3中的元素就可以互相拖拽了,是不是很简单。

 dragula([ ],{ })拥有两个参数,第一个参数是拖拽区域的集合,第二个是拖拽的默认值的对象,比如代码中的direction就是决定拖拽时水平还是垂直排序。

2.几个比较常用的默认值设置

这里的可拖拽区域就是div2和div3

参数作用
direction拖拽排序方向,默认‘vertical’垂直方向,'horizontal’为水平方向
revertOnSpill拖拽时,若在在可拖拽区域外停止拖拽,物品会去到上一次经过的可拖拽区域。加上revertOnSpill:true 可以让它回到原点
removeOnSpillremoveOnSpill:true,当在可拖拽区域外停止拖拽时,删除该拖拽的物品
mirrorContainer生产镜像(分身)的位置,默认document.body
copy是否可以复制(拖拽时拖出一个分身而不是本身)。设为true时所有的可拖拽区域的拖拽都变为复制分身。除此还可以接受函数,如: copy: (el, source) => { if (source.id === 'div2' ) { return true; } else {return false; } }。此处的source是被拖拽物品所在的可拖拽区域,这样,只有div2中的物品会进行复制
accepts可以接受拖拽物品的可拖拽区域 accepts: (el, target) => { if (target.id === 'div2' ) return false; return true} }这样,设置后,div2的区域将不接受拖入物品
moves通过它可以设定可拖拽物品的可拖拽区域moves: (el, container, handle) =>{ return handle.classList.contains('handle'); }这样设定后,物品只有classname中有handle字段的区域可以被拖拽

3.实例化对象的api

const dragSet = dragula([ ], { });
api作用
drake.containers可拖拽区域的集合,并且可以添加或删除区域
drake.dragging任何一个物品被拖拽时变为true(官方的解释,但这个api我个人用起来感觉有问题)
drake.start(item)调用时开始拖拽
drake.end()调用时结束拖拽
drake.cancel(revert)调用时结束拖拽取消拖拽
drake.remove()调用时移除当前被拖拽的元素
drake.destroy()强制结束正在进行的拖拽动作,并删除所有的可拖动区域

 drake.on(‘drag’,(…e)=>{ })有两个参数,第一个是想要进行的操作类型,第二个是一个方法体

drake.on( )参数作用
drake.on(‘drag’)el,source拖拽时会一直调用
drake.on(‘dragend’)el拖拽时结束时会调用
drake.on(‘drop’)el, target, source, sibling放下时调用
drake.on(‘cancel’)el, container, source拖拽取消时调用
drake.on(‘remove’)el, container, source物品删除时调用
drake.on(‘shadow’)el, container, source阴影位置变化时调用
drake.on(‘shadow’)el, container, source阴影位置变化时调用
drake.on(‘over’)el, container, source移入某个可拖拽区域时调用
drake.on(‘out’)el, container, source移出某个可拖拽区域时调用

4.样式

 使用时需要手动引入dragula提供的样式,不然拖拽的阴影样式会出错

.gu-mirror {
    position: fixed !important;
    margin: 0 !important;
    z-index: 9999 !important;
    opacity: 0.8;
    -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)';
    filter: alpha(opacity=80);
    pointer-events: none;
    width: 90px;
    border: 1px solid transparent;
    padding: 0px;
    text-align: center;
}

.gu-hide {
    display: none !important;
}

.gu-unselectable {
    -webkit-user-select: none !important;
    -moz-user-select: none !important;
    -ms-user-select: none !important;
    user-select: none !important;
}

.gu-transit {
    opacity: 0.2;
    -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=20)';
    filter: alpha(opacity=20);
}

5.嵌套拖拽

 由于dragula的易用性,嵌套拖拽也变的十分简单,以下代码将div1做成了一个可拖拽的区域。接着,将div1中的dropAbleArea1和div2做成了另一组可拖拽的区域。这样一来,div2中的物品就可拖到dropAbleArea1中,dropAbleArea1可在div1中上下拖动排序。

 	const dragSet2 = dragula([document.getElementById('dropAbleArea1'),document.getElementById('div2')], {
            direction: 'horizontal',
        });
    const dragSet3 = dragula([document.getElementById('div1')], {
            moves:  (el, container, handle) =>{
                return handle.classList.contains('handle');
            }
        });
    const data1=[{id:'dropAbleArea1',name:'dropAbleArea1'},{id:'area2',name:'area2'},{id:'area3',name:'area3'}]
    const data2=[{id:'1',name:'green'},{id:'2',name:'blue'},{id:'3',name:'red'}]

 
    return (
        <div  className='dragulaPage'>
            <div id='div1'className='dragContainers'>
                {data1.map((data)=>(
                    <div  key={data.id} style={{height:'100px',border:'1px solid',width:'100%',marginTop:'10px'}}>
                        <div className='handle' style={{height:'30%'}}>++ {data.name}</div>
                        <div   id={data.id} style={{height:'70%',borderTop:'1px solid',width:'100%',display:'flex'}}></div>
                    </div>
                ))}
            </div>
            <div id='div2' className='dragContainers'>
                {data2.map((data)=>(
                    <div  key={data.id} className='dragBlock' style={{border:`1px solid ${data.name}`}}>{data.name}</div>
                ))}
            </div>
          </div>
      )

在这里插入图片描述
在这里插入图片描述

6.结语

 由于dragula是直接对元素进行操作,不涉及任何数据的处理,所以十分的简便丝毫不显臃肿,于此相对的,编程人员需要处理的数据就大大增加,所以涉及大量复杂数据的拖拽不建议使用。最后,文中列出的属性和api是我认为最有可能用到的一些,并不是全部,如果这些无法满足你的要求,不妨再仔细阅读一遍官方文档。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值