안녕하세요. 제 이름은 왕푸펭입니다.
저는 수석 풀스택 엔지니어이자 17.5k 오픈 소스 프로젝트인 PMP의 저자입니다. 지금은 Notion 스타일의 지식베이스를 개발 중입니다
React Nextjs 및 Supabase를 사용하여 AI 작성 및 협업을 포함하는 HuashuiAI.
이 글에서는 React와 dnd-kit으로 정렬 가능한 트리 리스트 드래그 앤 드롭을 구현하는 방법을 공유하겠습니다. 소스코드 링크는 글 하단에 있습니다.
Dnd-kit은 React 생태계에서 흔히 사용되는 드래그 앤 드롭 도구이며 기본적으로 정렬 기능을 지원합니다.
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd} > <SortableContext items={items} strategy={verticalListSortingStrategy} > {items.map(id => <SortableItem key={id}> <p>But it can only support the one-level list. If we want to implement a multi-level nested list (or tree), we have to customize it.</p> <h2> Define state date structure </h2> <p>Modern front-end frameworks such as React Vue are data-driven views, so defining data structures first and then considering UI rendering.</p> <p>The most common data structure definition for multi-level nested lists (trees) is as follows, and virtual DOM vnode is also defined in this way.<br> </p> <pre class="brush:php;toolbar:false">const defaultItems = [ { id: 'A', children: [] }, { id: 'B', children: [ { id: 'B1', children: [] }, { id: 'B2', children: [ { id: 'B2a', children: [] }, { id: 'B2b', children: [] }, ], }, ], }, { id: 'C', children: [] }, { id: 'D', children: [ { id: 'D1', children: [] }, { id: 'D2', children: [] }, ], }, { id: 'E', children: [] }, ]
상태 데이터 구조가 중첩되어 있기 때문에 가장 먼저 떠오르는 것은 UI 구조를 함께 중첩하고 렌더링하는 것입니다.
먼저 그런 다음 하위 런닝 효과는 다음과 같습니다. 문제는 동일한 레벨 내에서는 드래그 앤 드롭 정렬이 허용되지만, 컨텍스트가 아니기 때문에 교차 레벨 정렬이 불가능하다는 점입니다. 이는 합리적입니다 중첩이 불가능하므로 여러 레벨을 단일 레벨로 변환해야 합니다. 그러나 먼저 계층 구조의 깊이를 표시하고 두 번째로 해당 항목에 어떤 상위 노드가 있는지 확인하려면 각 항목에 조상 ID 속성을 추가해야 합니다. 변환 후 렌더링 효과는 다음과 같으며, 이제 드래그하여 정렬할 수 있습니다. 단, 상태 정렬이 수정되기 전까지는 적용되지 않습니다. 또한 조상 ID의 계층적 관계를 통해 이동할 수 있는지 여부도 확인할 수 있습니다. 상위 노드는 하위 노드로 이동할 수 없습니다. 그렇지 않으면 루프가 종료됩니다. 예를 들어 위 그림에서 B2를 B2a의 위치로 드래그하려는 경우 B2a의 조상 ID에 B2가 포함되어 있음을 알 수 있습니다. 항목을 하위 항목으로 끌 수 없기 때문에 이는 불가능합니다. 작업의 용이성을 위해 데이터는 Zustand 글로벌 스토어에 배치됩니다. Dnd-kit은 드래그된 요소를 activeItem으로, 배치된 대상 위치를 overItem으로 참조합니다. 따라서 상태 데이터를 수정한다는 것은 activeItem을 overItem의 위치로 이동하는 것을 의미합니다. 단일 레벨인 경우 Dnd-kit에서는 직접 수정할 수 있는 arrayMove 메소드를 제공합니다. 문서 링크 https://docs.dndkit.com/presets/sortable 하지만 다단계 중첩 목록(트리)에서는 이를 직접 구현해야 하는데, 이는 다소 번거롭습니다. 핵심 코드는 여기에 있으며, 참고용으로 소스 코드(기사 끝 부분)를 다운로드할 수 있습니다. 아래 그림과 같이 A를 B 아래로 드래그하면 A가 B 내부가 아닌 전체적으로 B 아래로 이동하게 됩니다. 이 문제를 해결하려면 B 뒤에 B의 하위 요소가 있는지 확인해야 합니다. 그렇다면 해당 하위 요소에 overItem을 할당하세요 그런 다음 현재 활성 요소를 항목의 첫 번째 요소에 삽입합니다. 소스코드 링크는 여기 https://github.com/wangfupeng1988/react-dnd-sortable-demo 그나저나 저는 국제적인 취업 기회를 찾고 있습니다. 기회가 되시면 제 Github 프로필에 저와 연결해 주세요. 위 내용은 dnd-kit에 반응하고 트리 목록 드래그 앤 드롭 정렬 가능 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!
단일 레벨로의 다중 레벨 변환이 가능합니다.
interface IItem {
id: string
ancestorIds?: string[]
children?: IItem[]
}
function flatten(items: IItem[]): IItem[] {
return items.reduce<IItem[]>((acc, item) => {
acc.push(item)
if (item.children) {
const children = item.children.map((i) => ({
...i,
ancestorIds: [...(item.ancestorIds || []), item.id], // add ancestorIds
}))
acc.push(...flatten(children))
}
return acc
}, [])
}
상태 데이터 수정
문제가 발생했습니다.
끝