일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- python
- 프로그래밍
- javascript
- 배열
- 프로그래머스
- 동적계획법
- OS
- 백준
- 카카오
- sql
- 리트코드
- typescript
- Doitvue.js입문
- Level1
- CS
- web
- 코테연습
- 리액트
- VUE
- 파이썬
- 웹프로그래밍
- Medium
- C++
- dp
- LeetCode
- Level3
- 고득점Kit
- 자바스크립트
- react
- Level2
- Today
- Total
[Vue] Vuex 본문
Vuex
global state를 관리하는 라이브러리
local state는 하나의 컴포넌트에만 영향을 미치지만 global state는 어플리케이션 전체에 영향을 미칠 수 있다.
why
global state를 관리하는 것은 어려울 수 있다.
하나의 컴포넌트에 너무 많은 로직과 데이터를 포함하게 된다.
데이터의 변화를 예측할 수 없다.
에러를 일으킬 수 있고 추적이 어렵다.
Using store
main.js에 createStore를 통해 store를 생성한 후 app에 연결한다.
import { createApp } from 'vue';
import { createStore } from 'vuex';
import App from './App.vue';
const store = createStore({
state() {
return {
counter: 0,
};
}
});
const app = createApp(App);
app.use(store);
app.mount('#app');
다른 컴포넌트들에서는 $store.state
로 접근해서 값을 가져올 수 있다.
<template>
<base-container title="Vuex">
<h3>{{$store.state.counter}}</h3>
<button>Add 1</button>
</base-container>
</templa te>
##
Mutations
vuex는 state을 컴포넌트에 제공하지만 컴포넌트에서 직접 state를 변경하는 것은 이상적이지 않다. 각각 다른 컴포넌트에서 동시에 state를 변경할 경우 값을 추적하기 힘들기 때문이다. vuex는 mutations
을 이용해 state의 변경이 모든 컴포넌트에서도 동일하게 이뤄지는 것을 보장한다.
store에 mutationd을 정의하고 빌드인 메소드 commit
을 통해 호출할 수 있다.
const store = createStore({
state() {
return {
counter: 0,
};
},
mutations: {
increment(state) {
state.counter = state.counter + 2;
}
}
});
export default {
methods: {
addOne() {
this.$store.commit('increment');
}
}
}
payload
payload 객체를 이용해 mutaion으로 인수를 넘길 수 있다.
increase(state, payload) {
state.counter = state.counter + payload.value;
}
두 가지 방식으로 해당 mutation을 호출할 수 있다.
this.$store.commit('increase', {value: 10});
this.$.commit({
type: 'increase',
value: 10,
})
Getter
state를 직접 읽어오는 것도 이상적인 방식이 아니다. state의 값을 변경해서 가져오고 싶을 때 해당 state를 참조하는 모든 컴포넌트에 각각 computed를 작성해줘야하므로 일관성이 떨어질 수 있다.
이를 위해 Getter
를 사용한다.
getter가 받는 인자
state
getters
getters: {
finalCounter(state) {
return state.counter * 2;
}
각 컴포넌트에는 getter로 접근해 computed state를 가져올 수 있다.
this.$store.getter.finalCounter;
getter는 다른 getters의 값을 가져와 쓸 수 있다.
normalizedCounter(_, getters) {
const finalCounter = getters.finalCounter;
if (finalCounter < 0) {
return 0;
}
if (finalCounter > 100) {
return 100;
}
return finalCounter;
}
Action
Mutations
는 반드시 동기로 처리되어야한다. state 값이 변경되는 도중에 비동기 처리를 위해 멈춘다면 에러가 발생할 것이다. 따라서 비동기 처리를 위해서는 mutation에서 component로 가는 사이에 Actions
을 거친다.
actions: {
increment(context) {
setTimeout(() => {
context.commit('increment')
}, 2000)
},
increase(context, payload) {
setTimeout(() => {
context.commit('increment', payload)
}, 2000)
}
},
action은 dispatch
로 가져와 쓸 수 있다.
this.$store.dispatch({
type: 'increase',
value: 10,
})
Mapper
MapGetter
mapGetter
로 원하는 computed state를 한꺼번에 가져올 수 있다.
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters(['finalCounter'])
},
}
</script>
MapActions
action을 한꺼번에 가져온다
methods: {
...mapActions(['increase', 'increment'])
}
payload는 인자로 넘기면 된다.
<template>
<Button @click="increase({value: 10})">add 10</Button>
<Button @click="increment">add 10</Button>
</template>
배열이 아닌 객체 형태로 키와 action을 매핑할 수도 있다.
Module
기능별로 모듈을 나눈 후 스토어에 등록하여 사용할 수 있다.
이 때 각 모듈의 state는 local이다.
const counterModule = {
state() {
return {
counter: 0,
}
},
mutations: {
increment(state) {
state.counter++
},
increase(state, payload) {
state.counter += payload.value
},
},
actions: {
increment(context) {
setTimeout(() => {
console.log(context)
context.commit('increment')
}, 2000)
},
increase(context, payload) {
setTimeout(() => {
console.log(context)
context.commit('increase', payload)
}, 2000)
},
},
getters: {
finalCounter(state) {
return state.counter * 3;
},
normalizedCounter(_, getters) {
const finalCounter = getters.finalCounter;
if (finalCounter < 0) {
return 0;
}
if (finalCounter > 100) {
return 100;
}
return finalCounter;
},
}
};
const store = createStore({
modules: {
numbers: counterModule
},
state: {
isLoggedIn: false,
},
mutations: {
setAuth(state, payload) {
state.isLoggedIn = payload.isAuth
}
},
actions: {
login(context) {
context.commit('setAuth', {isAuth: true});
},
logout(context) {
context.commit('setAuth', {isAuth: false});
}
},
getters: {
userIsAuthenticated(state) {
return state.isLoggedIn
}
},
})
메인 스토어의 state와 getter에 접근하려면 rootState
, rootGetters
를 쓴다.
testAuth(state, getters, rootState, rootGetters) {
console.log(state, getters, rootState, rootGetters)
return rootState.isLoggedIn
},
namespaced
namespace
를 지정하면 해당 모듈의 getter,state 등을 호출할 때 namespace를 붙여야한다. 이 때 namespace
는 메인 스토어에 모듈을 등록할 때 사용한 키값이 된다.
const counterModule = {
namespaced: true,
// (....)
}
const store = createStore({
modules: {
numbers: counterModule
},
// (...)
}
...mapGetters('numbers', ['finalCounter'])
this.$store.commit('numbers/increment')
this.$store.getters['numbers/normalizedCounter'];
..mapActions('numbers', {
inc: 'increment',
inr: 'increase'
})
'Web > Vue' 카테고리의 다른 글
[Vue] Options API => Composition API (0) | 2022.10.21 |
---|---|
[Vue] Router (0) | 2022.09.13 |
[Vue] v-model (0) | 2022.08.11 |
[Vue] 뷰 CLI에서 사용하는 NPM (0) | 2022.08.08 |
[Vue] Vuex, 뷰의 반응성, SSR, 뷰 개발을 위한 웹 팩 (0) | 2022.08.08 |