프로젝트

Vue 3 + Vuex 로 Todo-List 만들어보기 (2)

김쨔뿌 2022. 4. 27. 06:38

옙 원래 어제 밤에 적을 예정이었는데 밥먹고 9시 반에 기절하고 5시쯤에 깼다. 뭐지??

이번 글에서는 컴포넌트 생성하고 store 연결까지만. 아침에 쓰고있는데 이따 회사가야함 ㅇㅇ

cli를 맞치고 나면 초기 파일이 이렇게 들어가있다. 헬로월드 안쓰니까 지워주고..

 

App.vue 보면 아래와 같이 되어있는데

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Welcome to Your Vue.js App" />
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>

<HelloWorld msg="어쩌구"> 이거랑 script에 import 한 헬로월드 컴포넌트를 지워주고.... components 안의 것도 지워준다.

로고는 이쁘니까 쓸거임.

 

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
</template>

<script>
export default {
  name: "App",
  components: {},
};
</script>

깰끔~

 

그럼 이제 todo-list 에 무슨 컴포넌트가 들어갈 지 생각해보자.

카드형식으로 만들거니까 카드 컴포넌트 하나 만들어주고, 

카드 컴포넌트들이 들어갈 부모컴포넌트 하나 만들어줘야겠다.

컴포넌트를 만들땐 두개이상의 단어를 사용하고 각 단어의 첫글자를 대문자로 써준다. 이래야 나중에 import 할 때 편해진다.

 

// TodoCard.vue
<template></template>
<script></script>
<style lang="sass"></style>

 

뷰가 직관적이긴 한게... html이랑 비슷하다. script는 js 쓰는 공간이고 style은 css 쓰는 공간이다. template 안에는 html 처럼 div나 span이나 그런거 쓰면 됨 ㅇㅇ 골격을 저기서 만든다.

 

골격은 대충 사용할 것들 생각해서 써주자.

나는 카드에 제목과 내용을 넣을 거고 이후 삭제/편집기능을 구상할 예정이니 아래와 같이 만들었음.

<template>
  <section class="todo-card">
    <h3>title</h3>
    <p>comment</p>
    <button>edit</button>
    <button>delete</button>
  </section>
</template>

 

이제 script 부분에 이 놈의 이름을 때려넣어줘야한다.

<script>
export default {
  name: "TodoCard",
};
</script>

 

저 이름이 이제 이 컴포넌트를 다른 컴포넌트에서 불러올때 얘가 투두카드구나! 해주는 거임.

 

TodoMain.vue 에서 불러와보자.

// TodoMain.vue
<template>
  <todo-card></todo-card>
</template>
<script>
import TodoCard from "./TodoCard.vue";

export default {
  name: "TodoMain",
  components: { TodoCard },
};
</script>
<style scoped></style>

<todo-card>가 TodoCard 컴포넌트다. 그냥 <TodoCard> 써도 됨.

App.vue에도 똑같이 TodoMain.vue 를 불러와주자.

 

//App.vue
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <todo-main></todo-main>
</template>

<script>
import TodoMain from "./components/TodoMain.vue";
export default {
  name: "App",
  components: { TodoMain },
};
</script>

잘 들어간다. 

 

이제 vuex의 store를 볼 차례..!!

// store/index.js
import { createStore } from "vuex";

export default createStore({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {},
});

state는 초기데이터를 넣어두는 곳,

getters는 수식이 중복될때 사용한다던데...안써봐서 아직 잘 모름.

mutations 이랑 actions 가 이제 state의 값을 변경해주는 함수를 넣는 공간인데 mutations는 동기식, actions 는 비동기식이다.

modules 는 index.js 한 곳에 다 적기 힘들어서 파일 분리를 하고, 분리한 파일을 가져오는 곳.

 

일단 state에 임시 데이터를 넣어주자. 

state: {
    todoList: [
      {
        id: 0,
        title: "제목이다!",
        comment:
          "마라탕에 푸주, 두부피, 죽순, 어묵만 가득 채워서 먹어보고싶다.",
        done: false,
      },
      {
        id: 1,
        title: "제목이다!제목이다!",
        comment: "영어공부를 좀 혀야하는디 에혀 우짜냐",
        done: false,
      },
      {
        id: 2,
        title: "제목이다!제목이다!제목이다!",
        comment: "뷰 생각보다 재밌다 하지만 여전히 리액트가 너무 좋은.",
        done: false,
      },
    ],
  },

 

리스트에서 각 객체에 id가 있어야 나중에 반복해서 꺼내서 html에 넣어줄 수 있다. key값을 지정해줘야하기때문.

done은 이 todo를 실행했는지 안했는지의 여부. 처음이니 일단 다 false.

 

TodoMain 에서 TodoCard 컴포넌트를 store에 있는 임시 값대로 반복시킬것임.

//TodoMain.vue

<template>
  <todo-card v-for="todoItem in getCardList" :key="todoItem.id"></todo-card>
</template>
<script>
import TodoCard from "./TodoCard.vue";

export default {
  name: "TodoMain",
  components: { TodoCard },
  computed: {
    getCardList() {
      return this.$store.state.todoList;
    },
  },
};
</script>

컴포넌트에서 스토어에 있는 값 불러오는건 너무..간단하다! 와! 

this.$store 써주면 store 로 연결된다. 내가 넣은 임시 데이터의 경로는 this.$store.state.todoList 이다. 

computed는 무언가의 값을 리턴해주는 함수들을 넣어준다. 기본적으로 가독성을 위한 함수를 넣는다고 함.

그래서 computed에 getCardList라는 함수를 만들어주고 리턴값에  this.$store.state.todoList를 써준다.

 

<template>안에서 엘리먼트를 배열대로 반복해줄땐 v-for 를 써주면 된다.

v-for="아이템 in 리스트" 의 형식으로 써주는데 리스트 안에 있는 것 하나하나가 아이템이 된다. 즉, 리스트는 기존에 따로 명명되어있어야하고 아이템은 내가 임시로 정해주는 리스트 안의 것들에 대한 이름일 뿐임. 

그리고 key값이 반드시 있어야 한다. 그래야 반복할 녀석들이 각각 다른 것들인지 알 수 있기 때문.

 

위에서는 <todo-card>를 getCardList()의 return 값인 this.$store.state.todoList 안의 객체수 만큼 반복시키고 있다. key로는 this.$store.state.todoList 의 객체 하나하나에 들어간 id 값을 넣어주었다.

반복 자체는 잘 되어 나온다. 이제 저 텍스트들을 바꿔주자.

 

TodoCard 에서 부모한테서 받는 값을 props 에서 정해줄 수 있다.

//TodoCard.vue

<script>
export default {
  name: "TodoCard",
  props: {
    item: Object,
  },
};
</script>

props 안에 저런 식으로 어떤 타입의 값을 받아올지, 그리고 걔를 뭐라고 부를지 정해주자.

나는 TodoMain 으로부터 객체타입의 값을 받아올거고 item이라 부를 것임. 

받아온 값들을 이제 template안의 맞는 위치에 넣어주자. 

// TodoCard.vue
<template>
  <section class="todo-card">
    <h3>{{ todoItem.title }}</h3>
    <p>{{ todoItem.comment }}</p>
    <button>edit</button>
    <button>delete</button>
  </section>
</template>

 

TodoMain.vue로 돌아가서 위에서 정한 props 의 이름인 item 을  <todo-card> 태그 안에 :item="" 의 형식으로 적어준다. :를 붙여야 "" 안에서 변수같은걸 쓸 수 있음. 

//TodoMain.vue
<template>
  <todo-card
    v-for="todoItem in getCardList"
    :key="todoItem.id"
    :item="todoItem"
  ></todo-card>
</template>

TodoCard에 넘겨줄 객체는 당연히 todoItem이다. 왜냐면 저게 store에서 넣어준 임시값을 getCardList에서 리턴해주고 있는 리스트 내의 객체 하나하나를 가리키는 거니까!! 

그럼 이제 진짜 잘 나온다. 히야~

 

....원래 오늘 못해도 삭제기능까지 하려했는데 졸림... 좀만 더 자고 일어나서 출근해야겠음.

다음 글에서 추가기능, 삭제기능하고 시간 되면 편집기능까지 넣어야지. 그럼 20000.