因为使用了react.js技术栈,所以封装优先考虑输入和输出。基于数据驱动去渲染页面、控制拖拽元素的顺序。由于我不考虑兼容IE8等旧版本浏览器,拖拽的效果采用了HTML5的拖放(Drag 和 drop)。当然,如果要求兼容性丰富,使用鼠标点击的相关事件也很简单。实现的效果如下:第一步是先了解H5拖放的相关属性,MDN上有详细的说明,链接链接有一点需要注意的是,react.js会给所有的属性事件名称前加上"on",后面则为驼峰式写法。例如原生的click事件,在react.js里应使用onClick事件。我的组件使用的拖放属性如下:

draggable 当设置为true时,当前控件可以拖拽

onDragStart 控件开始被拖拽时触发的事件,它提供一个dataTransfer.setData()方法,将必要的数据存储在对象中便于在其它方法中调用

onDragOver 规定当前控件可以接收拖拽的组件的方法,一般在此方法中阻止冒泡

onDragEnter 拖动后鼠标进入另一个可接受区域时触发,通过它可以实现移入效果

onDragLeave a拖到b,离开b的时候触发,可以用于监听消除移入效果的时机

onDrop 当控件被“释放”到一个有效的释放目标位置时触发,我在这个方法中处理数据,并通过它调用onChange方法,将value值暴露给父组件


draggable 当设置为true时,当前控件可以拖拽onDragStart 控件开始被拖拽时触发的事件,它提供一个dataTransfer.setData()方法,将必要的数据存储在对象中便于在其它方法中调用onDragOver 规定当前控件可以接收拖拽的组件的方法,一般在此方法中阻止冒泡onDragEnter 拖动后鼠标进入另一个可接受区域时触发,通过它可以实现移入效果onDragLeave a拖到b,离开b的时候触发,可以用于监听消除移入效果的时机onDrop 当控件被“释放”到一个有效的释放目标位置时触发,我在这个方法中处理数据,并通过它调用onChange方法,将value值暴露给父组件

其中draggable,onDragStart是被“拖拽”方需要设置的属性,onDragOver,onDragEnter,onDragLeave和onDrop是被“拖入”方需要设置的属性。不过对于我的拖拽排序组件,每一个元素都是拖拽和拖入方第二步,既然“她"是react.js的组件, 按照习惯,简单的将输入属性定为为value,同时,暴露onChange事件监听value的变化,并将其暴露给父组件,同时,暴露一个属性sortKey告诉组件使用哪个key作为排序字段。
既然涉及到排序,同时允许指定组件每个元素的内部子组件,我将输入数据格式定义为一个数组对象,其中content可以为reactNode:
value: [

{

content: 'div1',

code: '01',

sort: 0,

},

{

content: 'div2',

code: '02',

sort: 1

},

{

content: 'div3',

code: '03',

sort: 2

},

{

content: 'div5',

code: '05',

sort: 5

},

{

content: 'div4',

code: '04',

sort: 4

}]
value: [

{

content: 'div1',

code: '01',

sort: 0,

},

{

content: 'div2',

code: '02',

sort: 1

},

{

content: 'div3',

code: '03',

sort: 2

},

{

content: 'div5',

code: '05',

sort: 5

},

{

content: 'div4',

code: '04',

sort: 4

}]根据value我去生成可排序组件的每个node,关键代码如下:
// 生成拖拽组件
createDraggleComponent(data, sortKey, style, uId) {

return data.sort(this.compare(sortKey)).map((item) => {

return (


className={styles.content}

key={item.code}

draggable={true}

onDragEnter={this.dragenter.bind(this)}

onDragLeave={this.dragleave.bind(this)}

onDragStart={this.domdrugstart.bind(this, item[sortKey], item.code, uId, item)}

onDrop={this.drop.bind(this, item[sortKey], data, sortKey, uId)}

onDragOver={this.allowDrop.bind(this)}

style={{ ...style }}>{item.content}