图标的拖动排序
2018-12-14 本文已影响16人
楠楠_c811
最近遇到一个新的需求,要求弹窗展示一个图标列表,然后每个图标都可以拖动排序......
what?
拖动排序?然后满脑子就是碰撞、判断、上下左右......
为什么一个小图标要做的这么复杂?能看不就好了么?
......当然,如果你打不过产品经理,还说不过他,你还能做什么呢????
乖乖去找方法解决喽,还能咋地?
当然了,我一直认为技术不能逾越市场,也不能让技术引领产品潮流。因为毕竟术业有专攻,在产品设计这件事情上,听产品的不是错。
这块代码是一个的react的子组件,最后会被作为组件调用。
// 我是一个独立封装的子组件
import React from 'react'
// 定义当前要拖拽的图标
let curDragIndex = null;
// 封装子组件
export default function dragSort(props){
// 定义所有需要拖拽的图标
let container = props.children;
// from 是要拖拽的列,to是行,封装变化事件函数
function onChange(from, to){
// 如果是同一个,说明没有执行拖拽,直接返回
if(from === to ) return ;
// 定义当前被拖拽的数据
let curValue = props.data;
// 定义执行后当前最新的数组
let newValue = arrMove(curValue, from, to);
// 判断传进来的参数是否有 onChange 方法,如果有就执行父级的onChange
if(typeof props.onChange === 'function'){
// 如果调用父级的onChange函数方法,就根据传参返回最新的数组
return props.onChange(newValue, from ,to);
}
}
return (
<div>
{/* 循环遍历表格的每一项*/}
{container.map((item, index)=>{
// 判断是不是react组件。用来增加代码的健壮性,防止渲染的时候出错
if(React.isValidElement(item)){
// 如果是,克隆并返回一个新的 ReactElement (内部子元素也会跟着克隆),
// 新返回的元素会保留有旧元素的 props、ref、key,也会集成新的 props(只要在第二个参数中有定义)
return React.cloneElement(item, {
// 设置元素可拖动
draggable:"true",
// 开始拖拽
onDragStart: function(){
// 获取被拖拽的数据的起始位置下标
curDragIndex = index
},
// 拖拽过程中
onDragEnter: function() {
// 执行onChange函数,获取最新位置,达到互换效果
onChange(curDragIndex, index)
// 当前拖拽的数据顶替之前这个位置的数据
curDragIndex = index;
},
// 拖拽停止
onDragEnd: function(){
curDragIndex = null;
// 判断如果这里有调用函数事件
if(typeof props.onDragEnd === 'function'){
// 就让他调用停止事件
props.onDragEnd()
}
}
})
}
// 将最终的item return 出去
return item;
})}
</div>
)
}
// 设置函数,接收参数
function arrMove(arr, fromIndex, toIndex){
// 合并原有数组赋值给一个新数组
arr = [].concat(arr);
// 取到传进来的起始位置的值 item是需要插入的内容
let item = arr.splice(fromIndex, 1)[0];
// 将插入的内容加到目的点的后面,返回一个新的数组
arr.splice(toIndex , 0, item);
return arr;
}
封装好这个组件之后,剩下的就是传参调用了。我这个拖拽排序是写在一个弹框里的,实现效果是打开弹框,获取到数据,然后拖拽操作。
// 记得要在最上面引入封装的组件文件哦
class Currency extends Component{
//拖动排序事件
handleTableChange = (pagination, filters, sorter) => {
this.setState({newSort: sorter.order, newSortField: sorter.field}, () =>
this._getTokenList(pagination.current - 1, pagination.pageSize, this.state.newSort, this.state.newSortField, this.state.searchInput, this.state.searchBlack, this.state.searchAble, this.state.searchAsset));
};
handleDragMove = (data, from, to) => {
this.setState({
curMoveItem: to,
tokenList: data
})
};
handleDragEnd = () => {
this.setState({
curMoveItem: null
})
};
render(){
return(
<div>
// 弹框
<Modal
title="我是antd的弹框组件"
visible={this.state.sort}
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<p>上下拖动可调整展示排序</p>
// 我是上面封装的组件哦
<DragSort onDragEnd={this.handleDragEnd}
onChange={this.handleDragMove}
data={this.state.tokenList}>
{
this.state.tokenList.map((token,index)=>{
return (
<ul>
<li>
<div key={index}>
<span>{token.id}</span>
<img style={{width: 50, height: 50, margin:10 }} src={token.icon} />
<span>{token.symbol}</span>
</div>
</li>
</ul>
)
})
}
</DragSort>
</Modal>
</div>
)
}
}