Drag & Drop 를 이용해서 리스트 요소 순서 바꾸기
How to Implement Drag and Drop Feature for Your React Component
todo list
를 구현했는데, 뭔가 너무 아쉬웠다. 평소에 구현해보고 싶었던 기술중에 Drag & Drop
이 있었는데 todo list
에 적용하기 너무 좋아보여서 시도했다.
인터페이스
DnD 의 인터페이스로는 크게 4가지가 존재한다.
DateEvet
와 DataTranfer
만 알아보자.
DragEvent
Drag 관련 이벤트. 여기서 중요한건 이벤트의 발동 주체가 2가지로 나뉜다는것임.
1. 드래그 요소
마우스로 클릭하고 끌고 다니는 요소
drag
dragStart
dragEnd
2. 드래그 요소와 겹치는 아이템
dragEnter
dragOver (필수로 구현)
dragLeave
drop (필수로 구현)
여기서 주목할 건 Drag
요소를 다른 요소 어딘가에 놓으면 그에 대한 이벤트는 drop
이 발생하고 이 drop
을 핸들링 하는 곳이 Drag
된 요소가 아니라 그 요소와 겹치는 아이템이라는 것.
여기서 의문이 생긴다. Drag
된 요소가 아니라 그 요소가 떨어진 곳에서 Drop
이벤트 핸들러를 실행한다면, Drag
된 요소의 정보는 어떻게 넘겨주는거지? 그 의문은 DataFransfer
에서 해결된다.
DataTransfer
https://developer.mozilla.org/ko/docs/Web/API/DataTransfer
get
,set
이외에도 여러 메서드, 프로퍼티가 있다. 필요하면 위의 링크로 가서 보자.
실제로 드래그를 이용해서 리스트 요소의 순서를 바꾸는걸 생각해보자.
요소를 마우스로 잡는다.
마우스로 잡은 요소에서
dragStart
이벤트를 핸들링한다.
끌고 다닌다.
원하는 곳에 내려놓는다.
내려놓은 곳의 요소에서
drop
이벤트가 발동된다.
우리는 1번에서 요소에 대한 정보를 어딘가에 저장해야하고, 그 정보를 3번에서 이용해야한다. 이걸 해주는게 DataTransfer
다. 사용법은 매우 간단하다. setData
를 통해 데이터를 저장하고, getData
를 이용해서 저장된 정보를 불러온다.
실제 사용은 아래처럼 하면된다.
localStorage
처럼 get
, set
으로 사용하면 된다.
실제 사용하기
todoList 내의 todo 들을 드래그해서 옮기는 코드를 예로 든다. 코드는 여기를 눌러서 확인하자.
아래의 코드는 미래 재사용을 위해
useDragAndDrop
이라는 커스텀훅으로 만들었다.
1. draggable 속성 넣기
지금까지 내가 만든 웹요소들은 드래그가 모두 불가능했었다. 왜? 바로
draggable
속성을 넣지 않았기 때문이다. 즉draggable
속성을 넣으면 요소들은 드래깅이 가능해진다.
draggable
속성을 넣음으로써 API 를 사용할 수 있게 된다.
2. onDragStart 핸들러
드래그의 시작을 알려준다. 인터페이스 부분에서 설명했다시피 이 부분에서 옮기는 요소에 대한 정보를 저장해야한다.
코드를 분석해보자면
setIsDragging
현재
todo
가 드래그 하는 중이라는걸 알려주는state
다.이 값을 통해
todo
는 자신이 드래깅중인지 또는 아닌지를 알 수 있다.css
핸들링에 사용할 수 있다.
e.dataTransfer.effectedAllowed = move
드래그를 해보면 디폴트로 마우스 아래에
+
버튼이 생긴다. 이 버튼을 막아준다. https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#drageffects.
e.dataTransfer.setData('text/plain', id);
드래그 하는 요소의 정보를 담는다.
3. onDragOver 핸들러
Dropzone
tkdghk
e.preventDefault();
기본으로 발동하는 다른 이벤트들을 막는다. (Touch, pointer events..)
setIsDragOver(true);
현재 요소가 드래그 요소의 아래 깔려있음을 말해준다.
4. onDrop 핸들러
Dropzone
const movingTarget = e.dataTransfer.getData('text/plain');
이전에 저장한 데이터를 가져온다.
callback()
todo
요소의 위치를 바꾸는 함수다.
Last updated