State란 무엇인가?
state는 컴포넌트 간에 공유할 data를 말한다. 각 컴포넌트에서의 data 속성과 동일하기 때문에, 각 컴포넌트의 인스턴스에서 data()
속성을 사용하는 대신, Vuex에 state로 등록하여 사용한다.
State 등록하기
store.js에 state(데이터)를 등록한다.1
2
3
4
5
6
7
8
9
10
11
12// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
// state안에 데이터를 등록
state: {
value: 10
}
});
State 사용하기
가져와서 사용할 각 컴포넌트에서 Vuex의 state에 접근하여 사용한다.1
2
3
4
5
6
7// App.vue
<template>
<div id="app">
// store.js의 state에 있는 데이터(value)에 접근하여 가져와서 사용
{{ this.$store.state.value }}
</div>
</template>
위와 같은 방식으로, 어떤 컴포넌트든 Vuex(store.js)에 접근하여 state를 가져와 사용할 수 있다.
그러나, Template의 표현식은 최대한 간소화해야 한다. 다음과 같이 computed
를 사용해서 state에 접근할 수 있다.
1 | <template> |
Getters란 무엇인가?
Getters는 인스턴스의 computed(계산된 속성)과 같은 역할을 한다. 인스턴스에서 computed는 이미 어떤 값이 캐싱되어 있어, 종속된 값이 변경되지 않으면, 이미 계산되 값이 바로 나오고, 종속된 값이 변경된 경우에만 다시 재계산되어 나온다.
그래서, Getters를 사용하면 여러 컴포넌트에서 같은 로직을 비효율적으로 사용하는 것을 막는다. 즉, 각 컴포넌트에서는 수행 로직을 호출만 하면, Vuex의 Getters를 보내주어, 코드의 가독성과 성능이 좋아진다.
Getters 등록하기
store.js에 getters를 등록한다.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'vue', complete: true },
{ id: 2, text: 'react', complete: false },
{ id: 3, text: 'angular', complete: true }
]
},
// todos의 complete가 true인 데이터만 필터
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.complete)
}
}
});
Getters 사용하기
1 | // App.vue |
mapGetters 사용하기
Vuex에 내장된 helper 함수 중, mapGetters를 사용하여, 좀 더 간단하게 작성할 수 있다.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// App.vue
<template>
<div id="app">
{{ doneTodos }}
</div>
</template>
<script>
// mapGetters를 import
import { mapGetters } from 'vuex'
// computed에서 mapGetters를 사용
export default {
// Vuex 의 Getters 메서드 명과 App.vue 메서드 명이 동일할 때, [] 사용
computed: mapGetters([
'doneTodos'
]),
// Vuex 의 Mutations 메서드 명과 App.vue 메서드 명을 다르게 매칭할 때, {} 사용
computed: mapGetters({
// 앞 doneTodos 해당 컴포넌트의 메서드를, 뒤 'doneTodos'는 Vuex의 getters를 의미
doneTodos: 'doneTodos'
})
}
</script>
Mutations란 무엇인가?
Mutations(변이)란, Vuex의 데이터, 즉 state 값을 변경하는 로직들을 의미한다. Vuex 저장소에서 실제로 상태를 변경하는 유일한 방법이다.
Mutations 특징
- 모든 state의 변화를 추적해야 하기 때문에, 순차적, 즉 동기적으로 일을 처리한다.
- 컴포넌트의 인스턴스에서는 methods에서 사용하여, Vuex의 mutations에 접근한다.
- 이때, 인자를 받아서 Vuex로 보낼 수 있다.
Getters와의 차이점
- 인자를 받아서 Vuex에 넘겨줄 수 있다.
- methods에서 사용(Getters는 computed에서 사용)
Actions와의 차이점
- mutations: 동기적 로직
- actions: 비동기적 로직
만약, 여러 개의 컴포넌트에서 같은 state 값을 동시에 제어하게 되면, state 값이 어느 컴포넌트에서 호출해서 어떻게 변경된지를 추적하기가 어렵기 때문에, mutations에서는 동기적으로 하나씩 일을 처리하여, 상태의 변화를 정확하게 추적할 수 있다.
Mutations 등록하기
먼저 Vuex(store.js)에 mutations를 등록해야 한다.1
2
3
4
5
6
7
8
9
10
11
12
13
14// store.js
export default new Vuex.Store({
mutations: {
getTodo (state, payload) {
state.todoList = payload;
},
// function을 같이 써줘도 된다.
addTodo: function(state, payload) {
state.todoList = [...state.todoList, payload];
},
},
})
mutations는 getters와 다르게, 인자를 받아서 Vuex에 넘겨줄 수 있다.
- 첫번째 인자: state로, store.js에 있는 state를 의미한다.
- 두번째 인자: payload로, 컴포넌트에서 보내주는 데이터이다.(만약 데이터가 없다면, 생략 가능)
Mutations 사용하기
컴포넌트의 인스턴스에서는 methods에서 사용하여, commit
으로 Vuex(store.js)의 mutations에 접근한다.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30// App.vue
<template>
<section>
<div class="row justify-content-center mt-4">
<input v-model="inputField" v-on:keyup.enter="addTodo" class="mr-1" placeholder="Todo Item" />
<button @click="addTodo" class="btn btn-primary">Add Todo</button>
</div>
</section>
</template>
<script>
export default {
// store.js에서의 mutations 중 'getTodo'에 접근
mounted() {
this.$store.commit('getTodo')
},
// store.js에서의 mutations 중 'addTodo'에 접근
methods: {
addTodo: function() {
if(this.inputField) {
// 'addTodo'는 mutations에 있는 'addTodo', this.inputField는 Vuex(store.js)에 넘겨줄 데이터
this.$store.commit('addTodo', this.inputField);
this.inputField = '';
}
},
}
}
</script>
참고로, main.js에 전역 인스턴스에 store를 등록했기 때문에, this.$store를 사용할 수 있다.
mapMutations 사용하기
Vuex에 내장된 helper 함수 중, mapMutations를 사용하여, 좀 더 코드 가독성을 높일 수 있다.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// App.vue
// mapMutations를 import 해야함
import { mapMutations } from 'vuex'
methods: {
// Vuex 의 Mutations 메서드 명과 App.vue 메서드 명이 동일할 때, [] 사용
...mapMutations([
'addTodo'
]),
// Vuex 의 Mutations 메서드 명과 App.vue 메서드 명을 다르게 매칭할 때, {} 사용
...mapMutations({
addTodo: 'addTodo' // 앞 addTodo는 해당 컴포넌트의 메서드를, 뒤 'addTodo'는 Vuex의 mutations를 의미
})
}
Actions란 무엇인가?
actions란, Vue에서 비동기적으로 처리되야 하는 것들을 관리하기 위한것이다. 즉, 서버와의 http 통신이나 setTimeout() 등과 같이, 결과를 받아올 타이밍이 예측되지 않은 로직을 actions에 선언하고 처리한다.
대표적으로 비동기인 다음의 2가지를 actions에서 주로 사용한다.
- http통신
- setTimeout()
<1> http 통신: axios 사용1>
Actions 등록하기
먼저 Vuex(store.js)에 actions를 등록해야 한다.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// store.js
export default new Vuex.Store({
actions: {
addTodo: function(context, payload) {
axios.post('http://localhost:4000/todos', {
id: 4,
text: payload,
completed: false
})
.then((res) => {
// 상태(state)가 변경된 것을 추적하기 위해, mutations의 메소드를 호출(commit)
context.commit('addTodo', res.data)
})
.catch((err) => {
console.log(err);
})
},
}
})
Mutations 등록하기
actions에 등록을 했어도, 상태가 변경된 것을 추적하기 위해서는 mutations의 메소드를 호출(commit) 해야한다. 그리고, mutations에 actions에 등록한 메소드를 작성한다.1
2
3
4
5mutations: {
addTodo (state, todo) {
state.todoList = [...state.todoList, todo]
},
}
Actions 사용하기
actions를 호출할 때는 dispatch
를 사용한다.
1 | // App.vue |
mapActions 사용하기
Vuex에 내장된 helper 함수 중, mapActions를 사용하여, 좀 더 간단하게 작성할 수 있다.
1 | // App.vue |
<2> setTimeout() 사용2>
Actions 등록하기
먼저 Vuex(store.js)에 actions를 등록해야 한다.1
2
3
4
5
6
7
8
9
10// store.js
export default new Vuex.Store({
delayTime: function (context, payload) {
return setTimeout(function () {
commit('addTodo', payload); // mutations에 있는 'addTodo' 호출
}, 5000);
}
})
Mutations 등록하기
actions에 등록을 했어도, 상태가 변경된 것을 추적하기 위해서는 mutations의 메소드를 호출(commit) 해야한다. 그리고, mutations에 actions에 등록한 메소드를 작성한다.1
2
3
4
5mutations: {
addTodo (state, todo) {
state.todoList = [...state.todoList, todo]
},
}
Actions 사용하기
actions를 호출할 때는 dispatch
를 사용한다.1
2
3
4// App.vue
addTime(time) {
this.$store.dispatch('delayTime', time);
}