实际需求,在同一个模块内部,可以通过拖拽设置排序,在拖拽时,如果进入目标区域,则成为当前模块中的一个,从原来的模块中删除当前的拖拽元素
//模块标题上面的所触发的onDrop事件,需要添加默认事件的阻止行为
handleTitleOndrop=(index,ev)=>{
const {dragElement,items} = this.state;
let dataarr = this.state.type.filter((item,i)=>index==i)
dataarr[0].list.push(dragElement)//当前模块下面的list添加当前拖拽的元素
ev.preventDefault();
let listArr = items;
listArr = listArr.filter(item=>item.id !=dragElement.id )//从原列表中删除当前推拽的元素
this.setState({
items:listArr
})
}
//渲染模块类型的列表
renderTitle(){
return(
<div>
{
this.state.type.map((item,i)=>{
return(
<div className='title'
onDrop={(event)=>{this.handleTitleOndrop(i,event)}}
>{item.name}</div>
)
})
}
</div>
)
}
children=(node)=>{
var tmp = node.childNodes;
var arr = [];
tmp.forEach(function(item){
if(item.nodeType == 1){
arr.push(item);
}
});
return arr;
}
//拖拽开始的事件,保存当前元素的数据,然后添加一些属性
handleStart=(data,ev)=>{
this.setState({
dragElement:data
})
ev.target.setAttribute('id', 'test1')
ev.dataTransfer.setData("text/plain", ev.target.id);
}
//e.preventDefault()必须要阻止默认事件,不然触发不了ondrop这个事件
ondrop1=(e)=>{
const {dragbox,n} = this.state
e.preventDefault();
var data = e.dataTransfer.getData("text");
var nodes = document.getElementById(data);
dragbox.insertBefore(nodes, this.children(dragbox)[n]);
nodes.removeAttribute('id');
e.dataTransfer.clearData();
}
//handledragover:onDragOver,拖拽的移动事件触发,需要阻止默认事件ev.preventDefault();
handledragover=(ev)=>{
const {offsetTop} = this.state
ev.preventDefault();
const clientX = ev.clientX;
const clientY = ev.clientY;
let n = Math.round((clientY - offsetTop)/50) //50:带拖拽元素的高度
this.setState({
n:n
})
}
//渲染同一模块内的列表,如果要让一个原生的文本成为可以拖拽的元素,需要添加draggable="true"
render() {
return (
<div>
{this.renderTitle()}
<div id='dragbox'
onDrop={(e)=>{ this.ondrop1(e)}}
onDragOver={(e)=>{this.handledragover(e)}} >
{this.state.items.map((item,index)=>
<div
id={`dragImg${index}`}
draggable="true"
onDragStart={(event)=>this.handleStart(item,event)}
className='itembg'
>{item.content}</div>
)}
</div>
</div>
);
}