import React, { useState, useRef } from 'react';
import Sortable from 'sortablejs';
import { onEnd, getNewAndOld } from 'carefree-sortable';
export interface SortableProps {
sortProps?: Sortable.Options;
children?: React.ReactNode;
nodeTag?: string;
warpProps?: any;
}
const ItemWarp = (props: SortableProps) => {
const { sortProps, children, nodeTag = 'div', warpProps = {} } = props;
const sortTableRef = useRef<Sortable>();
const newSortable = (node: HTMLElement) => {
if (!node) {
sortTableRef.current && sortTableRef.current.destroy();
return;
}
sortTableRef.current = Sortable.create(node, {
...(sortProps || {}),
});
};
return React.createElement(
nodeTag,
{ ...(warpProps || {}), ref: newSortable },
React.Children.map(children as React.ReactElement<any>[], (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, {
'data-id': child.key,
} as any);
}
}),
);
};
const config = [
{
title: '配置',
children: [
{ title: '配置 1.1' },
{ title: '配置 1.2' },
{ title: '配置 1.3' },
{ title: '配置 1.4' },
{ title: '配置 1.5' },
{ title: '配置 1.6' },
],
},
];
export default () => {
const [dataList, setDataList] = useState([
{
title: ' 测试1',
children: [
{ title: 'item 1.1' },
{ title: 'item 1.2' },
{ title: 'item 1.3' },
{ title: 'item 1.4' },
{ title: 'item 1.5' },
{ title: 'item 1.6' },
],
},
{
title: ' 测试2',
children: [
{ title: 'item 2.1' },
{ title: 'item 2.2' },
{ title: 'item 2.3' },
{ title: 'item 2.4' },
{ title: 'item 2.5' },
{ title: 'item 2.6' },
],
},
{
title: ' 测试3',
children: [
{ title: 'item 3.1' },
{ title: 'item 3.2' },
{ title: 'item 3.3' },
{ title: 'item 3.4' },
{ title: 'item 3.5' },
{ title: 'item 3.6' },
],
},
]);
const onUpdate = (evt: Sortable.SortableEvent) => {
const {
oldIndex,
newIndex,
pullMode,
oldParentPath,
oldPath,
newParentPath,
newPath,
} = getNewAndOld(evt);
console.log(evt);
const item = {
element: evt.item,
clone: evt.clone,
parentElement: evt.from,
};
// 需要对dom节点进行操作
// 1. 当前内部进行 排序
if (!pullMode) {
/* eslint-disable */
if (item.parentElement !== null) {
item.parentElement.removeChild(evt.item);
}
if (item.parentElement) {
const refChild = item.parentElement.childNodes[oldIndex] || null;
if (refChild) {
item.parentElement.insertBefore(evt.item, refChild);
} else {
item.parentElement.appendChild(evt.item);
}
}
} else if (pullMode === 'clone') {
// 克隆添加的 移除当前所在的位置
if (item.element && item.element.parentElement) {
item.element.parentElement.removeChild(item.element);
}
} else {
// 不是内部排序 不是 克隆 添加
if (item.element && item.element.parentElement) {
item.element.parentElement.removeChild(item.element);
}
if (item.parentElement) {
const refChild = item.parentElement.childNodes[oldIndex] || null;
if (refChild) {
item.parentElement.insertBefore(evt.item, refChild);
} else {
item.parentElement.appendChild(evt.item);
}
}
}
const result = onEnd(evt, dataList, config);
console.log(result);
setDataList(result.dataList);
};
const sortProps: Sortable.Options = {
group: 'nodes',
animation: 300,
fallbackOnBody: true,
onAdd: onUpdate,
onUpdate: onUpdate,
};
const loop = (data: any[], parentId?: string) => {
return (data || []).map((item, index: number) => {
const dataId = parentId ? `${parentId}-${index}` : `${index}`;
if (item.children) {
return (
<ItemWarp
sortProps={sortProps}
key={dataId}
warpProps={{ 'data-id': dataId, style: { padding: 20 } }}
>
{loop(item.children, `${dataId}`)}
</ItemWarp>
);
}
return <div key={dataId}>{item.title}</div>;
});
};
return (
<div>
<div>
配置
{config.map((item, index) => {
const { children } = item;
return (
<ItemWarp
sortProps={{
group: {
name: 'nodes',
pull: 'clone',
put: false,
},
animation: 300,
fallbackOnBody: true,
sort: false,
}}
key={`${index}`}
warpProps={{ 'data-id': `${index}` }}
>
{children.map((child, k) => {
return <div key={`${index}-${k}`}>{child.title}</div>;
})}
</ItemWarp>
);
})}
</div>
<ItemWarp sortProps={sortProps} warpProps={{ style: { padding: 20 } }}>
{loop(dataList)}
</ItemWarp>
</div>
);
};