10/20
Vue 인프런 강의 복습
Ref : https://www.inflearn.com/course/vuejs/
1. $nextTick()
: 다음 DOM 업데이트 사이클 이후 실행하도록 콜백함수를 인자로 전달한다. 데이터 변경한 직후에 사용해야한다.
- 사용 소스
//Card.vue
<header slot="header" class="cardView__header">
//1. isEditTitle === true
<b-form-input
v-model="inputTitle"
placeholder="타이틀을 입력하세요:-)"
class="cardView__inputTitle"
v-if="isEditTitle"
ref="inputTitle"
></b-form-input>
//2. isEditTitle === false
<span class="cardView__title" v-else @click="setEditTitle">
{{card.title}}
</span>
</header>
- v-if 디렉티브와 isEditTitle 변수를 이용해서 "input"과 "span"태그를 번갈아가면서 렌더링한다.
//Card.vue methods
setEditTitle() {
this.isEditTitle = true;
this.inputTitle = this.card.title.trim();
//this.$refs.inputTitle.focus(); //1.
this.$nextTick(() => { //2.
this.$refs.inputTitle.focus();
});
}
- $nextTick을 사용하지 않았을 경우, "$refs"를 통해서 input 태그를 참조하지 못햇다. => "isEditTitle"이 변경되어 DOM이 렌더링되는 것보다 //1.번 라인이 더 먼저 실행되는 것이 이유!!
- 따라서 this.$nextTick()에 해당 라인을 콜백함수으로 전달하여, 다음 DOM이 업데이트된 이후 실행하도록한다.
- Card 수정 로직
- 소스
//Card.vue
onEditCard() {
const listId = this.card.listId;
const title = this.inputTitle.trim();
//1.
const description = this.inputDesc.length ? this.inputDesc.trim() : null;
const id = this.cid;
//2.
if (!this.inputTitle.length) {
alert("카드 제목을 입력해주세요!");
//3.
this.inputTitle = this.card.title;
this.$nextTick(() => this.$refs.inputTitle.focus());
return false;
}
//4.
this.UPDATE_CARD({ id, title, listId, description })
.catch((err) => console.error(err))
.finally(() => {
this.restoreEdit();
//7.
this.fetchData();
});
},
//actions.js
UPDATE_CARD({ dispatch, state }, { id, title, description, listId, pos }) {
//5.
const payload = { title, description, listId, pos };
return api.card
.update({ id, payload })
.then(() => {
//6.
dispatch("FETCH_BOARD", { id: state.board.id });
})
.catch((err) => Promise.reject(err));
},
- description의 경우 payload를 구성할 때, 입력된 값이 빈 공백일 경우에 Null값으로 전달하기위해 작성한 라인입니다.
- 제목이 없을 경우를 예외처리했습니다.
- inputTitle에 기존 데이터의 title을 할당하고, 데이터가 변했으므로 DOM이 업데이트 된 이후, nextTick()을 이용해서 focus를 이동시켰습니다.
- Store의 메서드를 이용해서 수정 API를 호출합니다.
- 전달받은 데이터로 payload객체를 구성해서 데이터 전달 하는 부분을 간결하게만들었습니다
- 카드 수정이 완료되면, dispatch()를 이용해서 보드 데이터를 다시 서버로부터 가져와 Board 컴포넌트를 업데이트합니다.
- 마찬가지로, 현재 카드 컴포넌트에서도 데이터를 다시 서버로 부터 가져와서 업데이트합니다.
3. 카드 드래그 앤 드롭 구현
-
사용 라이브러리 : https://github.com/SortableJS/Vue.Draggable
-
사용 예시
//List.vue
<draggable
class="list-item__cardList list-group" //1.
:list="data.cards" //2.
:data-list-id="data.id"
draggable=".card-item" //3.
group="cardItem" //4.
@end="onEnd" //5.
>
<card-item
v-for="card in data.cards"
:data="card"
:key="card.pos"
/>
</draggable>
- 라이브러리에서 제공하는 "list-group" 클래스를 적용한다.
- :list에 배열 형태의 데이터를 바인딩한다.
- draggable 속성으로 드래그할 클래스를 설정한다.
- group 잘 모르겠지만 적용안할 경우, 드래그 앤 드롭이 안된다..!!
- @end이벤트와 이벤트 핸들러 onEnd
- 이벤트 핸들링, 이벤트 핸들러에 전달되는 객체
: https://github.com/SortableJS/sortablejs#event-object-demo
onEnd(event) {
//1. 2.
const { to, item } = event;
const listId = to.dataset.listId;
const currentCard = {
id: item.dataset.cardId * 1,
pos: 65535,
listId: listId * 1,
};
},
- to : 드롭된 draggable 컴포넌트 엘리먼트
- item : 드래그된 엘리먼트(여기서는 ".card-item")
=> *주의 사항 : ".card-item", 드래그할 엘리먼트의 :key가 중복되어서 duplicate에러가 발생할 경우, item이 제대로 선택되지 않는다!!!- from : 리스트 간 이동시 기존에 있던 draggable 컴포넌트 엘리먼트
- newIndex : to 엘리먼트를 기준으로 엘리먼트의 인덱스 값
- card-item :key 중복에러 방지를 위해 카드 생성 로직을 수정
//AddCard.vue
const pos = this.getPos();
getPos() {
//1.
const list = this.board.lists.filter(
(b) => b.id === this.listId
)[0];
//2.
const lastCard = list.cards[list.cards.length - 1];
//3.
return lastCard ? lastCard.pos * 2 : 65535;
}
- store에서 board데이터를 가져오고, 현재 속한 list의 id값을 통해 list데이터를 가져온다.
- 가져온 list의 cards프로퍼티에서 마지막 카드 데이터를 가져온다.
- 2번에서 가져온 카드가 있으면 가져온 카드의 pos 값에 2를 곱한 값을 리턴하고, 없으면 기본 pos 값인 65535를 리턴한다.
느낀점 : 강의에서 사용한 drag 라이브러리를 사용하지않고, 혼자 새로운 라이브러리를 사용하면서 기능을 익히는게 재미있기도 하고, 어렵지만 뿌듯했다 :-)
강의에서 사용한 방법을 현재 라이브러리에 맞춰서 사용할 계획이다.
* Reference
1. Vue.nextTick : https://kr.vuejs.org/v2/api/index.html#Vue-nextTick
Author And Source
이 문제에 관하여(10/20), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kyh196201/1020저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)