Vue3로 TodoList 만들기!
Vue3는 여기까지만 하고,, 다음글부터 Vue2에 typescript를 공부 할 예정이에요.
gh-pages : https://kimdongeun12.github.io/vue3-practice/
github : https://github.com/kimdongeun12/vue3-practice
폴더 구조
├─ src
│ ├─ App.vue
│ ├─ main.ts
│ └─ views
│ └─ todo
│ ├─ TodoList.vue // Todo의 View
│ ├─ TodoListWrap.vue // Todo의 List를 담고 있음
│ └─ TodoListWrite.vue // 리스트 작성 , 수정을 담당
폴더 구조는 위와같이 구성을했어요
TodoList.vue
<template>
<v-container>
<TodoListWrap
:Todolists="Todolists"
@isChecked="isChecked"
@deleteTodo="deleteTodo"
@showDialog="showDialog"
/>
<v-btn
class="floating"
icon="mdi-pencil"
size="small"
@click="showDialog()"
/>
<v-dialog v-model="dialog">
<TodoListWrite
:dialog="dialog"
:edits="edits"
:editTodo="edits.edit ? Todolists[edits.idx] : {}"
@hideDialog="hideDialog"
@submitDialog="submitDialog"
@editSubmitDialog="editSubmitDialog"
/>
</v-dialog>
</v-container>
</template>
export default defineComponent({
...
methods: {
showDialog(idx?: number) {
this.dialog = true;
if (idx !== undefined) {
this.edits.idx = idx;
this.edits.edit = true;
} else {
this.edits.idx = 0;
this.edits.edit = false;
}
}
},
...
});
</script>
<style lang="scss" scoped>
.floating {
position: fixed;
right: 24px;
bottom: 24px;
}
</style>
TodoListWrap.vue
<template>
<div class="listsWrap">
<v-card
class="mx-auto my-list"
v-for="(item, idx) in Todolists"
:key="idx"
:class="{ 'mx-auto active': item?.checked }"
width="400"
>
<template v-slot:title>
<v-btn
variant="text"
icon="mdi-check"
size="small"
@click="$emit('isChecked', idx)"
/>
{{ item?.title }}
</template>
<v-card-text> {{ item?.contents }} </v-card-text>
<v-card-actions class="justify-end">
<v-btn variant="outlined" @click="$emit('showDialog', idx)">
수정
</v-btn>
<v-btn variant="outlined" @click="$emit('deleteTodo', idx)">
삭제
</v-btn>
</v-card-actions>
</v-card>
<div class="text-center" v-if="Todolists?.length === 0">
할 일 목록이 없습니다.<br />
우측 아래 버튼을 클릭하여 추가해주세요.
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "TodoListWrap",
components: {},
props: {
Todolists: Object,
},
data() {
return {};
},
});
</script>
<style lang="scss" scoped>
.listsWrap {
display: block;
& > div + div {
margin-top: 20px;
}
.active:deep .v-card-title .v-btn__content {
color: #ff0000;
}
}
</style>
파일을 작성하는데 그렇게 중요하다고 느끼는건 별로 없지만 작업하면서 2가지정도 느낀게 있는데 css에서는 scoped를 이용하여 작업을 하는경우가 대다수인데 가끔식 Vuetify에서 스타일이 안먹히는 경우가 있어요 그때는 :deep
을 사용하면 해결이 되더라구요 정답은 아니지만 저같은경우는 v-card의 아이템 체크아이콘 색상을 변경해야할때 사용했어요.
props같은 개념은 React와 조금 비슷하면서도 다르다고 느꼈어요
:아이템명
바인드로 props를 전달 할 수 있으며 Function같이 이벤트를 넘길때에는
@함수명
으로 넘길 메소드를 넘기시면되요 자식한테 넘긴 메소드는
emit('함수명' , 전달할 값)으로 사용 할 수 있어요
아직 제가 많이 해보지를 않아서 양반향 바인딩이 얼마나 편리한지는 모르겠어요 하지만 단반향으로만 줄 수 있던 react보다 처음으로 vue를 입문 할 때는 편리한거 같아요
자세한 코드는 상단의 깃허브를 이용하여 확인해주시면 될거같아요
오늘도 좋은하루 되세요 ;)