Vue — 두 목록 사이 이동
항목을 같은 목록 안에서 재정렬하거나 다른 목록으로 이동합니다. 두 영역은 같은 scope와 group="tasks"를 공유하고 각 areaId는 고유합니다. 항목 ID는 이동 후에도 유지됩니다.
직접 실행
섹션 제목: “직접 실행”항목 왼쪽 손잡이를 잡고 오른쪽 빈 목록에 놓으십시오. 완료 수가 늘어나고 왼쪽 목록에서 해당 항목이 제거됩니다. 초기화는 모든 항목을 원래 순서로 되돌립니다. 이 예제의 이동 조작은 포인터 기반입니다.
<script setup lang="ts">import { ref } from 'vue';import { SortableRoot, SortableArea } from 'comins-sortable/vue';const props = withDefaults(defineProps<{ lang?: string }>(), { lang: 'ko' });const ko = props.lang === 'ko';type Item = { id: string; label: string };const initial = [{ id: 'plan', label: ko ? '문서 설계' : 'Design the docs' }, { id: 'build', label: ko ? '예제 구현' : 'Build an example' }, { id: 'review', label: ko ? '코드 검토' : 'Review the code' }];const todo = ref<Item[]>([...initial]);const done = ref<Item[]>([]);function reset() { todo.value = [...initial]; done.value = []; }</script><template> <div class="demo" data-demo="sortable-vue"> <div class="demo-toolbar"><span>{{ ko ? '손잡이를 잡고 다른 목록으로 이동하세요.' : 'Drag a handle into the other list.' }}</span><button @click="reset">{{ ko ? '초기화' : 'Reset' }}</button></div> <SortableRoot> <div class="transfer-board"> <section class="transfer-column"> <div class="list-heading">{{ ko ? '진행 예정' : 'To do' }}<span>{{ todo.length }}</span></div> <SortableArea v-model="todo" area-id="todo" group="tasks" item-key="id" handle=".task-handle" :component-props="{ class: 'task-list', 'aria-label': ko ? '진행 예정' : 'To do' }"> <template #item="{ item }"><div class="task" :data-task="item.id"><button class="task-handle" :aria-label="`${ko ? '드래그' : 'Drag'}: ${item.label}`">⠿</button><span>{{ item.label }}</span></div></template> </SortableArea> </section> <section class="transfer-column"> <div class="list-heading">{{ ko ? '완료' : 'Done' }}<span>{{ done.length }}</span></div> <SortableArea v-model="done" area-id="done" group="tasks" item-key="id" handle=".task-handle" :component-props="{ class: 'task-list', 'aria-label': ko ? '완료' : 'Done' }"> <template #item="{ item }"><div class="task" :data-task="item.id"><button class="task-handle" :aria-label="`${ko ? '드래그' : 'Drag'}: ${item.label}`">⠿</button><span>{{ item.label }}</span></div></template> </SortableArea> </section> </div> </SortableRoot> <p role="status" class="demo-status">{{ ko ? '완료' : 'Done' }}: {{ done.length }} / 3</p> </div></template>Vue 상태 계약
섹션 제목: “Vue 상태 계약”comins-sortable/vue의 SortableRoot와 SortableArea를 가져옵니다. v-model은 modelValue와 update:modelValue를 연결합니다. #item slot의 { item, index }로 항목을 렌더링합니다. React의 items/onItemsChange 계약을 그대로 적용하지 않습니다.
각 핸들의 touch-action: none과 user-select: none은 드래그 중 터치 스크롤·텍스트 선택 충돌을 줄입니다.
0.1.6의 Vue SFC 제네릭 추론을 사용합니다. SortableArea는 modelValue에서 항목·슬롯 타입을 추론하므로 별도 컴포넌트 타입 단언이 필요하지 않습니다.
검색어
섹션 제목: “검색어”다른 목록으로 이동, 목록 간 이동, 항목 옮기기, 드래그 앤 드롭, 재정렬, 공유 scope, transfer.