2021.10.31 - [프로그래밍/frontend] - [vue] 스스로 만들어보는 To Do List - 1
1을 통해 간단히 입력창과 버튼을 통해 리스트를 추가해보았다. 이제 새로운 vue 라이브러리를 써보고, 좀 더 그럴싸하게 바꿔봐야겠다.
vuex 를 추가해 상태관리를 쉽게 해보자
이전에는 props, emit 등을 활용해 컴포넌트간 데이터 전달과 이벤트 전달로 할일 추가를 구현했다.
하지만 만약 앱이 커지면 이런 방식으로는 머리가 아파질 수 있다.
애플리케이션의 크기가 커질수록 데이터가 거쳐야하는 컴포넌트가 많아지고 복잡해져서 로직파악이 어려울 때가 있다고 한다.
우리 팀에서 다루는 vue 앱을 볼때는 그런게 덜했는데 알고보니 그때 사용된 것이 vuex였다.
vuex 가 필요한 이유
vue의 중앙형 상태 관리 및 저장소
만약 이름을 변경하는 컴포넌트가 있다고 하자. 이름을 보여주는 이름표 컴포넌트와는 관계의 거리가 상당히 멀다. '이름' 이라는 상태 변화의 흐름을 파악하려면 시간이 오래걸리고 복잡하며, 연관되어있는 컴포넌트끼리 emit, props 등의 키워드가 추가되는 게 강제될 것이다.
컴포넌트 간의 관계가 복잡하면, 써야하는 코드도 많아져 피곤해진다.
상태를 관리하기 위해 Vuex라는 저장창고를 둔다면 위 그림처럼 복잡해지는 컴포넌트 트리에서도 상태관리가 편리해질 것이다.
Vuex 로 기존코드를 변경해보자
나의 경우에는 vuex 적용을 통해 이전에 props,emit으로 App.vue에서 다른 컴포넌트들로 관리했던 할일 목록 todos
을 vuex로 관리할 것 이다.
1. 설치 (next는 최신 버전의미, vue3사용자인 경우 권장npm install --save vuex@next
2. src/ 위치에 store.js 생성 후 코드 입력
import {createStore} from 'vuex'
// 저장소 생성이라고 보면된다
const store = createStore({
state() {
return {
// 컴포넌트에서 접근가능
todos: []
}
},
mutations: {
// state 변수는 외부 컴포넌트에서 수정 불가능하므로
// mutation 내 정의된 함수를 이용해야 상태의 변경 가능하다
addTodo(state, content) {
state.todos.push(content)
}
}
})
export default store
vuex는 state
, mutations
, actions
로 구분된다.state
로는 전역변수로 사용하고 싶은 (즉, 모든 컴포넌트에서 접근가능하게 하고픈) 데이터들을 정의하면 된다.mutations
에는 setter함수를 정의한다고 보면 된다. 외부 컴포넌트에서는 state 값들을 함부로 변경하지 않고 mutation 로 정의된 메서드들만을 통해서 상태가 변경될 수 있게 해야한다.
프로젝트가 커지면 커질수록 아무데서나 그때 상황에 맞게 상태를 변경한다면 찾기도 힘들고 문제가 생길수도 있으니 지혜로운 규칙이다라고 생각한다.
3. main.js 에 Vuex 사용하도록 추가
// src/main.js
import {createApp} from 'vue'
import App from './App.vue'
import store from './store.js'
const app = createApp(App)
app.use(store)
app.mount('#app')
vuex 라이브러리를 사용할 수 있도록 main.js 에 추가한다.
4.할일 Input 컴포넌트를 바꿔보자
// src/components/ToDoInput.vue
<template>
<div id="todoinput">
<input type="text" v-model="content" @keypress.enter="addToDo" />
<button type="button" @click="addToDo">제출</button>
</div>
</template>
<script>
export default {
data() {
return {
content: ''
}
},
methods: {
addToDo() {
// vuex commit
this.$store.commit('addTodo', this.content)
this.content = ''
}
}
}
</script>
<style></style>
기존에 props, emit 을 활용해 상위하위 컴포넌트간 데이터/이벤트를 전달하던 방식에서 vuex를 활용하도록 바꾸었다.
addToDo() 메서드에서 this.$store.commit('addTodo', this.content)
를 통해 vuex의 mutation 함수 내에 정의된 addTodo 메서드를 호출하게 된다.
vuex에서는 commit() 이라는 메서드를 통해서 mutation 함수를 컴포넌트에서 호출할 수 있도록 해준다. 첫번째 인자에 실행시키려는 mutation 메서드 이름을 넣고, 2번째 파라미터부터는 전달하려는 payload 값을 던져주면 된다.
5. 할일목록 출력 컴포넌트를 바꿔보자
// src/components/ToDoList.vue
<template>
<div id="todolist">
<div id="container" v-for="data in todos" :key="data.id">
<li id="text">{{ data }}</li>
</div>
</div>
</template>
```
<script>export default { computed: { todos() { return this.$store.state.todos } } }</script>
vuex 상태를 불러오기 위해서는 $store.state 가 필수이다. 그래서 상태값 불러오는 코드는 필연적으로 길어진다
그래서 사용된 컴퓨티드(computed) 속성은 템플릿의 데이터 표현을 더 직관적이고 간결하게 도와주는 속성이다.
만약 불러오려는 값이 길어질때 그대로 template영역에 불러오게 된다면 가독성이 매우 나빠질 것이다.
또한 template의 표현식은 최대한 가독성을 높여야하는 것을 vue에서도 권장한다
- computed 활용X :
<div id="container" v-for="data in this.$store.state.todos" :key="data.id">
- computed 활용 :
<div id="container" v-for="data in todos" :key="data.id">
vuex에서는 getter라는 기능도 지원하는데, 그건 나중에 해보도록 해야겠다.
위처럼 바꾸고 npm run serve를 통해 실행해보았다.
vuex로의 변경을 잘 마무리했다. vue는 라이브러리 하나하나 적용하는 것도 간단하고 이해하기 쉽다는 생각이 든다.
공부해가며 만들어가는거라 퀄리티는 허접하지만 이해는 더 잘 되는 것 같다.
다음은 그럴싸하게 todo item에 시간이나 달성조건 등을 구현해보자
'프로그래밍 > frontend' 카테고리의 다른 글
[vue] 스스로 만들어보는 To Do List - 1 (0) | 2021.10.31 |
---|---|
[React] 함수형 컴포넌트로 리액트 표 만들기 (table) (1) | 2020.08.06 |
[React] 리액트로 구구단 웹 페이지를 만들어보자 (0) | 2020.08.02 |