Skip to content

Commit 5e8f928

Browse files
committed
chore(components/draggable): 完成了 move 的逻辑
1 parent 6c95fbe commit 5e8f928

File tree

2 files changed

+103
-64
lines changed

2 files changed

+103
-64
lines changed

packages/components/src/draggable/demo/draggable-group.module.scss

+2-6
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,9 @@
1515
border: 1px solid #e6e6e6;
1616
background: #fff1d7;
1717
line-height: 32px;
18-
&[draggable='false'] {
19-
background: #f6f4f0;
18+
&.t-draggable__ghost {
19+
background: #f6a306;
2020
}
2121
}
22-
.data {
23-
padding: 0 20px;
24-
white-space: pre-wrap;
25-
}
2622
}
2723
}

packages/components/src/draggable/hooks/useDraggableChildren.ts

+101-58
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
type DraggableGroupContextProvider,
2+
DraggableGroupContextProvider,
33
draggableContext,
44
} from '~/draggable/DraggableGroup';
55
import {
@@ -25,29 +25,31 @@ export function useDraggableChildren({
2525
'transition' | 'children' | 'onChange' | 'list'
2626
>): ReactNode {
2727
const forceUpdate = useForceUpdate();
28-
const childrenRef = useFollowingRef(
28+
const modifyChildrenRef = useFollowingRef(
2929
outerChildren,
3030
(v) => Children.map(v, (i) => i) || [],
3131
);
32-
const listRef = useFollowingRef(list, (v) => v.slice());
33-
const { fromRef, toRef } = useContext(draggableContext);
32+
const listRef = useFollowingRef(list, (v) => ({
33+
origin: v.slice(),
34+
modify: v.slice(),
35+
}));
36+
const { fromRef, toRef, type } = useContext(draggableContext);
3437

35-
const preverRef = useRef<DraggableGroupContextProvider | null>(null);
3638
const stateRef = useRef<{ readonly id: symbol; index: number }>({
3739
id: Symbol(times++),
3840
index: -1,
3941
});
4042

4143
const [children] = useChildrenWithRefs(
42-
childrenRef.current,
44+
modifyChildrenRef.current,
4345
(el, props, idx) => {
4446
const id = stateRef.current.id;
45-
const item = listRef.current[idx];
47+
const item = listRef.current.modify[idx];
4648
const emit = (): void => {
47-
console.log('emit', stateRef.current.id, preverRef.current);
49+
console.log('emit', stateRef.current.id);
4850
// preverRef.current = null;
4951
if (isListChanged()) {
50-
const result = listRef.current.slice();
52+
const result = listRef.current.modify.slice();
5153
console.log('onchange', result);
5254
onChange?.(result);
5355
}
@@ -63,25 +65,42 @@ export function useDraggableChildren({
6365
// 拖动目标元素事件
6466
function getDragSideEvents() {
6567
const left: DOMAttributes<HTMLElement> = {
68+
onDragStart: (e: DragEvent) => {
69+
const dataTransfer = e.dataTransfer as DataTransfer;
70+
// dataTransfer.setData('text', `draggable:${index}`);
71+
dataTransfer.effectAllowed = 'move';
72+
const from: DraggableGroupContextProvider = {
73+
drop(id2) {
74+
if (type === 'move' && id2 !== id) {
75+
removeItem(item);
76+
}
77+
from.cancel = undefined;
78+
emit();
79+
},
80+
cancel(_id2): void {
81+
if (type === 'move') {
82+
updateChildrenOf(el, listRef.current.modify.indexOf(item));
83+
}
84+
},
85+
children: el,
86+
item,
87+
id,
88+
};
89+
fromRef.current = from;
90+
// const target = e.currentTarget as HTMLElement;
91+
// target.classList.add(cls.__.ghost);
92+
},
6693
onDragEnd: (e: DragEvent) => {
67-
const target = e.currentTarget as HTMLElement;
68-
target.classList.remove(cls.__.ghost);
69-
console.log('onDragEnd', item, target);
94+
// const target = e.currentTarget as HTMLElement;
95+
// target.classList.remove(cls.__.ghost);
7096
toRef.current?.cancel?.(id);
71-
emit();
97+
fromRef.current?.cancel?.(id);
98+
// emit();
7299
fromRef.current = null;
73100
toRef.current = null;
74101
stateRef.current.index = -1;
75102
e.preventDefault();
76103
},
77-
onDragStart: (e: DragEvent) => {
78-
const dataTransfer = e.dataTransfer as DataTransfer;
79-
// dataTransfer.setData('text', `draggable:${index}`);
80-
dataTransfer.effectAllowed = 'move';
81-
fromRef.current = { children: el, item, id };
82-
const target = e.currentTarget as HTMLElement;
83-
target.classList.add(cls.__.ghost);
84-
},
85104
};
86105
return left;
87106
}
@@ -111,12 +130,14 @@ export function useDraggableChildren({
111130
// if (from.id !== toRef.current?.id) toRef.current?.drop?.(id);
112131
const to = toRef.current;
113132
if (to) to.cancel = undefined;
133+
fromRef.current = null;
134+
toRef.current = null;
114135
emit();
115136
},
116137
// eslint-disable-next-line perfectionist/sort-objects
117138
onDragEnterCapture(e: DragEvent): void {
118-
const index = listRef.current.indexOf(item);
119-
console.log('enter', index, stateRef.current.index);
139+
const index = listRef.current.modify.indexOf(item);
140+
console.log('enter', id, index, stateRef.current.index);
120141
const target = e.target as HTMLElement;
121142
e.preventDefault();
122143

@@ -128,22 +149,36 @@ export function useDraggableChildren({
128149
return;
129150

130151
const from = fromRef.current;
131-
const prever = (preverRef.current = toRef.current || from);
152+
const prever = toRef.current || from;
132153
console.log(prever);
133154
if (!prever || !from) return;
134155
console.log(item, from.item);
135156
prever.enter?.(id);
136157

137158
console.log(prever.id, id, prever.id === id);
138-
const fromIndex = listRef.current.indexOf(from.item);
159+
const fromIndex = listRef.current.modify.indexOf(from.item);
139160
if (from.item !== item) {
140-
if (prever.id === id || fromIndex !== -1) move(fromIndex, index);
141-
else moveFromGroup(from.item, from.children, index);
161+
if (prever.id === id || fromIndex !== -1) {
162+
let toIndex = index;
163+
const modifyChildren = modifyChildrenRef.current[
164+
fromIndex
165+
] as ReactElement;
166+
// move 返回之前隐藏的 children 位置,如果存在则 index - 1
167+
if (
168+
type === 'move' &&
169+
fromIndex !== -1 &&
170+
fromIndex < index &&
171+
modifyChildren.props.className.includes(cls['--'].hidden)
172+
) {
173+
toIndex--;
174+
}
175+
move(cloneAndAddClassName(from.children), fromIndex, toIndex);
176+
} else moveFromGroup(from.item, from.children, index);
142177
} else {
143178
console.log('uuuuuuuuuuup');
144179
updateChildrenOf(
145-
cloneAndAddGhostClassName(
146-
childrenRef.current[fromIndex] as ReactElement,
180+
cloneAndAddClassName(
181+
modifyChildrenRef.current[fromIndex] as ReactElement,
147182
),
148183
fromIndex,
149184
);
@@ -155,25 +190,29 @@ export function useDraggableChildren({
155190
console.log('id===id', id2 === id);
156191
if (id2 !== id) {
157192
stateRef.current.index = -1;
158-
if (!list.includes(from.item)) {
193+
if (!listRef.current.origin.includes(from.item)) {
159194
removeItem(from.item);
160195
}
161-
// if (item === _item && type === 'move') {
162-
// console.log('mmmmmove');
163-
// // target.classList.add(cls['--'].hidden);
164-
// removeItem(_item);
165-
// }
196+
if (type === 'move') {
197+
console.log('mmmmmmmmm', item, from.item);
198+
updateChildrenOf(
199+
cloneAndAddClassName(from.children, cls['--'].hidden),
200+
listRef.current.modify.indexOf(from.item),
201+
);
202+
}
203+
return;
166204
}
205+
stateRef.current.index = -1;
167206
},
168207
cancel: (_id2): void => {
169208
console.log('oncancel', id, _id2, prever.id, target);
170209
stateRef.current.index = -1;
171-
if (!list.includes(from.item)) {
210+
if (!listRef.current.origin.includes(from.item)) {
172211
removeItem(from.item);
173-
preverRef.current = null;
212+
toRef.current = null;
174213
} else {
175214
console.log('ccccccccccccc');
176-
const index = listRef.current.indexOf(from.item);
215+
const index = listRef.current.modify.indexOf(from.item);
177216
// 还原成未加工状态
178217
updateChildrenOf(from.children, index);
179218
}
@@ -200,50 +239,54 @@ export function useDraggableChildren({
200239

201240
return children;
202241

203-
function move(from: number, to: number) {
204-
if (from === -1 || from === to) return;
205-
const temp = childrenRef.current.slice();
206-
temp[from] = cloneAndAddGhostClassName(temp[from] as ReactElement);
242+
function move(children: ReactElement, from: number, to: number) {
243+
// if (from === -1 || from === to) return;
244+
const temp = modifyChildrenRef.current.slice();
245+
temp[from] = children;
207246
moveItem(temp, from, to);
208-
childrenRef.current = temp;
209-
moveItem(listRef.current, from, to);
247+
modifyChildrenRef.current = temp;
248+
moveItem(listRef.current.modify, from, to);
210249
forceUpdate();
211250
}
212251
function moveFromGroup(item: unknown, children: ReactElement, to: number) {
213252
console.log('moveFromGroup', item, to, item);
214-
children = cloneAndAddGhostClassName(children);
215-
const temp = childrenRef.current.slice();
253+
children = cloneAndAddClassName(children);
254+
const temp = modifyChildrenRef.current.slice();
216255
insertToArray(children, to, temp);
217-
childrenRef.current = temp;
218-
insertToArray(item, to, listRef.current);
256+
modifyChildrenRef.current = temp;
257+
insertToArray(item, to, listRef.current.modify);
219258
forceUpdate();
220259
}
221260
function updateChildrenOf(children: ReactElement, index: number): void {
222-
const temp = childrenRef.current.slice();
261+
const temp = modifyChildrenRef.current.slice();
223262
// 还原成未加工状态
224263
temp[index] = children;
225-
childrenRef.current = temp;
264+
modifyChildrenRef.current = temp;
226265
forceUpdate();
227266
}
228-
function cloneAndAddGhostClassName(element: ReactElement): ReactElement {
267+
function cloneAndAddClassName(
268+
element: ReactElement,
269+
className = cls.__.ghost,
270+
): ReactElement {
229271
return cloneElement(element, {
230-
className: getClassNames(element.props.className, cls.__.ghost),
272+
className: getClassNames(element.props.className, className),
231273
});
232274
}
233275
function removeItem(item: unknown): void {
234-
const index = listRef.current.indexOf(item);
276+
const index = listRef.current.modify.indexOf(item);
235277
if (index === -1) return;
236-
listRef.current.splice(index, 1);
278+
listRef.current.modify.splice(index, 1);
237279

238-
const temp = childrenRef.current.slice();
280+
const temp = modifyChildrenRef.current.slice();
239281
temp.splice(index, 1);
240-
childrenRef.current = temp;
282+
modifyChildrenRef.current = temp;
241283
forceUpdate();
242284
}
243285
function isListChanged(): boolean {
286+
const { origin, modify } = listRef.current;
244287
return (
245-
list.length !== listRef.current.length ||
246-
list.some((it, i) => it !== listRef.current[i])
288+
origin.length !== modify.length ||
289+
origin.some((it, i) => it !== modify[i])
247290
);
248291
}
249292
}

0 commit comments

Comments
 (0)