๐ข ๋ค์ด๊ฐ๊ธฐ ์ ์
- ์ด๋ฒ ํฌ์คํ ์์ Vuex๊ฐ ๋ฌด์์ธ์ง ์์๋ณด๊ณ , ๊ฐ๋จํ ์์ ๋ฅผ ๊ตฌํํด๋ณธ๋ค.
- Vue CLI๋ก ์ค์นํ Vue.js ํ๋ก์ ํธ ํ๊ฒฝ์์ ์งํํ๋ค. Vuex๋ฅผ ์์ํ๊ธฐ ์ ์, ์๋ ๋ฐฉ๋ฒ์ผ๋ก Vue.js ํ๋ก์ ํธ๋ฅผ ์ค์นํด์ผํ๋ค.
- Intellij IDE ๋๋ WebStorm IDE
File
-New
-Project
-Vue.js
- npm
npm i -g @vue/cli
vue create 'ํ๋ก์ ํธ ๋ช '
- Intellij IDE ๋๋ WebStorm IDE
โ Vuex ๋?
Vuex๋ ํ๋ง๋๋ก ์๊ธฐํ์๋ฉด ์ํ(state)๋ฅผ ๊ด๋ฆฌํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
์ฌ๊ธฐ์ ์ํ๋ ๋ฌด์์ผ๊น?
new Vue({
// ์ํ
data () {
return {
count: 0
}
},
// ๋ทฐ
template: `
<div>{{ count }}</div>
`,
// ์ก์
methods: {
increment () {
this.count++
}
}
})
์ฌ๊ธฐ ๊ฐ๋จํ Vue.js ์ฑ์ด ์๋ค.
์ฌ๊ธฐ์ data()
๋ฅผ ์ฐ๋ฆฐ "์ํ(state)" ๋ผ๊ณ ๋ถ๋ฅธ๋ค. (์ปดํฌ๋ํธ ๊ฐ ๊ณต์ ํ ์ ์๋ ๋ฐ์ดํฐ)
๋ฐ๋ก ์ด ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ด Vuex ์ด๋ค.
โ Vuex๋ ์ธ์ , ์ ํ์ํ๊ฐ?
prop
์ด๋ ref
๋ฑ์ผ๋ก ์ปดํฌ๋ํธ ๊ฐ ๋ฐ์ดํฐ(์ํ)๋ฅผ ๊ณต์ ํ ์ ์๋๋ฐ ๊ตณ์ด Vuex๊ฐ ํ์ํ ๊น?
- ๊ณตํต์ ์ํ๋ฅผ ๊ณต์ ํ๋ ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ์๋ ๊ฒฝ์ฐ, ์ง๋์น๊ฒ ์ค์ฒฉ๋ ์ปดํฌ๋ํธ๋ฅผ ํต๊ณผํ๋ prop์ด ์๊ธฐ๊ฒ ๋๋ค. ์ด๋ ๋์ค์ ์ ์ง๋ณด์ํ๊ธฐ ํ๋ ๋ํดํ ์ฝ๋๊ฐ ๋ ์ ์๋ค.
- ๊ณตํต์ ์ํ๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์, ์ด ์ํ๊ฐ ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ๋์ผํ ์ํ๋ก ๊ด๋ฆฌ๋์ด์ผ ํ๋ค. Vue๋ ๋จ๋ฐฉํฅ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ํ๋ฅด๊ธฐ๋๋ฌธ์, ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ํ ์ํ๋ฅผ ๊ณต์ ํ๋ ๊ฒฝ์ฐ, ํ์ ์ปดํฌ๋ํธ๊ฐ์ ์ํ๊ณต์ /๊ด๋ฆฌ๊ฐ ๋ณต์กํด์ง ์ ์๋ค.
์ด ๋ ์ฐ๋ฆฐ Vuex๋ฅผ ์ฌ์ฉํ๋ค. ์ ์ ์๋ฏ์ด, ์ปดํฌ๋ํธ๊ฐ ๋ง์ ์ค๋ํ ๊ท๋ชจ์ SPA ์์ ์ ์ฉํ๊ฒ ์ฐ์ธ๋ค.
๐จ ์ฃผ์
์๋์์ ์ค๋ช
ํ๊ฒ ์ง๋ง Vuex ๋ store(์ ์ฅ์)๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
์ฆ, ์ํ(state)์ ์ ์ฅ์๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ธ๋ฐ, ์ด ์ ์ฅ์๋ผ๋ ๋ง ๋๋ฌธ์ Vuex๊ฐ ์ธ์
/์ฟ ํค localStorage ์ฒ๋ผ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ซํ์ง ์๋ ์ด์ ๊ณ์ ์ ์ง๋๋, Vuex ์ ์ฅ์์ ์ํ(state)๊ฐ ์ ์ฅ๋๋ ๊ฒ ์ฒ๋ผ ๋๊ปด์ง ์ ์๋ค.
ํ์ง๋ง Vuex ์ ์ํ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์๋ก ๊ณ ์นจ์ ์ด๊ธฐํ ๋๋ค.
Vuex๋ ์ปดํฌ๋ํธ ๋จ์์ data()
๊ฐ ๊ทธ์ ์ดํ๋ฆฌ์ผ์ด์
๋จ์์ data()
๊ฐ ๋ ๊ฒ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค. data()
๊ฐ localStorage์ ์ ์ฅ๋์ง ์๋๋ค. ์๋ก๊ณ ์นจํ๋ฉด ๋น์ฐํ ์ด๊ธฐํ๋จ..๐
์ํ๋ฅผ ์๋ก๊ณ ์นจ ์์๋ ์ ์ง ํ๊ณ ์ถ๋ค๋ฉด vuex-persistedstate(state - localstorage ๋๊ธฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ) ๊ฐ์ ๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ๋ค.
โ Vuex ์ค์นํ๊ธฐ
vue
vue add vuex
npm
npm install vuex --save
Yarn
yarn add vuex
(๋๋ npm ์ผ๋ก ์ค์นํด์คฌ๋ค)
Vuex๋ ์ํ(state)๋ฅผ ์ ์ฅํ๊ณ ์๋ ์ ์ฅ์(store)๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
Vuex๊ฐ ์ค์น๋์๋ค๋ฉด ์ด ์ ์ฅ์๋ฅผ ๊ด๋ฆฌํ๋ ํ์ผ์ ์์ฑํด์ฃผ์.
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
}
// ...
});
/src/store.js
/src
๊ฒฝ๋ก์ store.js
ํ์ผ์ ๋ง๋ค๊ณ ์์ ๊ฐ์ด ์
๋ ฅํด์คฌ๋ค.Vue.use()
๋ฅผ ํตํด Vue๊ฐ Vuex
์ฌ์ฉํจ์ ์ ์ธํ๊ณ , store
์ธ์คํด์ค๋ฅผ ์์ฑํด์ค ๊ฒ์ด๋ค.
import Vue from 'vue'
import App from './App.vue'
import { store } from "./store";
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store: store,
}).$mount('#app');
/src/main.js
main.js
์์ ๋ง๋ค์ด์ค store.js
๋ฅผ import
ํด์จ ๋ค Vue ์ธ์คํด์ค์ ์ฃผ์
ํ์.
์ฌ๊ธฐ์ ์ ๊น ์ ์ฝ๋์ ๋ํด ์ค๋ช ํ์๋ฉด,
Vue.config.productionTip
๋ Vue ์ฑ์ด ์ฒ์ ์คํ ๋ ๋ ๋์ค๋ ๊ฒฝ๊ณ ๋ฌธ(๋ฐฐํฌ์ ๋ํ ํ)์ ์ถ๋ ฅํ ๊ฒ์ธ์ง ๋ฌผ์ด๋ณด๋ ๋ด์ฉ์ด๋ค.false
๋ก ์ค์ ํ๋ฉด ๊ฒฝ๊ณ ๋ฌธ(๋ฐฐํฌ์ ๋ํ ํ)์ ์ถ๋ ฅํ์ง ์๋๋ค.
default ๋ false
์ด๋ค.
render: h => h(App)
์ ๋ค ๋จ๊ณ์ ๊ฑฐ์ณ์ ES6๋ก ๋ณํ๋ ๋ฉ์๋์ด๋ค.
// #1
render: function (createElement) {
return createElement(App);
}
// #2
render (createElement) {
return createElement(App);
}
// #3
render (h){
return h(App);
}
// #4
render: h => h(App);
ES6 ๋ฌธ๋ฒ์ด๋ผ๋ ๊ฒ์ ์ด์ ์๊ฒ ๊ณ ...
์ ํํ render() ๋ผ๋ ๊ฒ์ด ๋ฌด์์ ์๋ฏธํ๋ ๊ฑธ๊น?
์ ์ฝ๋์์ #1
์ ๋ณด๋ฉด render
๋ ์ค์ง์ ์ผ๋ก createElement()
์ ๋ฐํ ๊ฐ์ด๋ผ๋ ๊ฑธ ์์ ์๋ค.
์ฌ๊ธฐ์ createElement()
๋, Virtual DOM(๊ฐ์ ๋)์ ๋ง๋๋ ๋ฉ์๋์ด๋ค.
Virtual DOM(๊ฐ์๋)
<div>
<h1>My title</h1>
Some text content
<!-- TODO: Add tagline -->
</div>
์ ์ด๋ฏธ์ง๋ HTML ์ฝ๋๋ฅผ DOM ๋
ธ๋ ํธ๋ฆฌ๋ก ๋ํ๋ธ ๊ฒ์ด๋ค.
ํ
์คํธ, ์ฌ์ง์ด ์ฃผ์ ์กฐ์ฐจ ํ๋์ ๋ฉ์ด๋ฆฌ(๋
ธ๋)๊ฐ ๋์ด ํธ๋ฆฌ์ ํ ๋ถ๋ถ์ด ๋๊ฑธ ์ ์ ์๋ค.
์ด๋ฌํ ๋
ธ๋์ ์ด๋ ํ ๋ถ๋ถ์ด ์
๋ฐ์ดํธ ๋์ด์ผํ ๋, ์ ์ฒด ํธ๋ฆฌ๋ฅผ ๊ฐฑ์ ํ๋ ๊ฒ์ ๊ต์ฅํ ๋นํจ์จ์ ์ผ ์๋ฐ์ ์๋ค.
๊ทธ๋์ ๊ณ ์๋ ๋ฐฉ๋ฒ์ด ๋ฐ๋ก Virtual DOM์ด๋ค.
๊ฐ์ ๋์ ์
๋ฐ์ดํธ๊ฐ ํ์ํ ๋
ธ๋ ์ ๋ณด๋ง ์ ์ํ๊ณ ์๋ค.
๋๋ฌธ์ ์ฐ๋ฆฐ ์์ ์ ์ํ๋ ๋
ธ๋๋ง ์
๋ฐ์ดํธ ์์ผ์ค ์ ์๋ค. ์ ์ฒด ๋
ธ๋ํธ๋ฆฌ๋ฅผ ๊ฐฑ์ ํ์ง ์๊ณ ๋!
์ฐธ๊ณ ๋ก ์ด ์
๋ฐ์ดํธ๊ฐ ํ์ํ ๊ฐ์ ๋์ ๋
ธ๋๋ค์ VNode๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ด ๊ฐ์ ๋์ ์์ฑํ๋ ๋ฉ์๋๊ฐ ๋ฐ๋ก createElement()
์ด๋ค.
์ฌ์ฉ ์๋ฅผ ์ดํด๋ณด์
์ ์ฝ๋์ h1
ํ๊ทธ ๋ด์ title ๋ถ๋ถ๋ง ๊ฐฑ์ ์์ผ๋ณด๊ฒ ๋ค.
render: function (createElement) {
return createElement('h1', this.blogTitle)
}
h1
ํ๊ทธ์ ๋ด์ฉ์ this.blogTitle
๋ก ๋ณ๊ฒฝํ๊ฒ ๋ค๋ ๋ป์ด๋ค.
์ฌ๊ธฐ์ ์ ๊น, ์๋ฌธ์ ์ด ๋ค์ง ์๋๊ฐ?
render: function (createElement) {
return createElement(App);
}
์ ์ฝ๋์์ createElement
์ ์ ๋ฌ ์ธ์๊ฐ App
์ผ๋ก ํ๋์๋๋ฐ,
๊ฐ์ ๋ ์์ ์์ h1
, this.blogTitle
์ผ๋ก ์ ๋ฌ์ธ์๊ฐ ๋๊ฐ์ธ ๊ฑธ ์ ์ ์๋ค.
createElement(renderElement: String | Component, children: String | Array)
createElement(renderElement: String | Componenet, definition: Object, children: String | Array)
๊ฒฐ๋ก ์, createElement
์ ์ ๋ฌ์ธ์๋ 2๊ฐ์ผ์๋, 3๊ฐ์ผ ์๋ ์๋ค๋ ๊ฒ์ด๋ค.App
์ฒ๋ผ ์ ๋ฌ ์ธ์๋ฅผ ํ๋๋ง ๋ฐ์ ์ปดํฌ๋ํธ ์์ฒด๋ฅผ ๊ฐ์๋์ผ๋ก ๋ ๋๋ง ์ํฌ ์ ์๊ณ ,
์ ๋ฌ ์ธ์๋ฅผ ๋๊ฐ(h1
, this.blogTitle
) ๋ฐ์ h1
element ๋ฅผ this.blogTitle
์ด๋ผ๋ ๊ฐ์ผ๋ก ์
๋ฐ์ดํธํ๋ค๊ณ ์ ์ํ ์๋ ์๋ค.
์์ธํ ์์๋ณด๊ธฐ - ๊ณต์๋ฌธ์
์ด๋ก์จ render: h => h(App);
์ ๋ํด ์กฐ๊ธ์ด๋๋ง ์ดํดํ ์ ์๊ฒ ๋์๋ค.
์์ฝํ์๋ฉด,render: h => h(App)
ํจ์๋ ์ฌ์ค createElement(App)
์ ๋ฐํ ๊ฐ์ด๊ณ ,createElement()
๋ ๊ฐ์ ๋์ ๋ง๋ค์ด ๋ ๋๋ง ํ๋ ํจ์์ด๋ค.
๊ทธ๋ฆฌ๊ณ createElement
๋ฅผ h
๋ก ์์ฝํ ๋ค, ES6์ ํ์ดํํจ์๋ฅผ ์ด ๊ฒ์ด ์ง๊ธ์ render: h => h(App)
๋ผ๋ ๊ฒ์ด๋ค.
(h
๋ hyperscript
์ ์ฝ์๋ก HTML ๊ตฌ์กฐ๋ฅผ ์์ฑํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์๋ฏธํจ.)
store: store
๋ Vue์ Vuex(store
)๋ฅผ ์ฃผ์
ํ๋ค๋ ๋ป์ด๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก router
๋ ์ฃผ์
ํ ์ ์๋ค.
โ Vuex์ ํต์ฌ ์์ฑ
์ store.js
์์ ์๋์ ๊ฐ์ด state
์์ฑ์ ์จ์คฌ๋ ๊ฒ ๊ธฐ์ต๋๋๊ฐ?
export const store = new Vuex.Store({
state: {
}
// ...
});
/src/store.js
state
์ ๊ฐ์ ์์ฑ์ด store
๋ด์ ํฌ๊ฒ 5๊ฐ์ง๊ฐ ์๋ค.
state
getters
mutations
actions
modules
์ง๊ธ๋ถํฐ ์ด 5๊ฐ์ง ์์ฑ์ ๋ํด ์ฐจ๊ทผ์ฐจ๊ทผ ์์๋ณด์.
๐ state
state
๋ ์ํ(state)์ ์งํฉ์ด๋ค.
Vuex ๋ ๋จ์ผ ์ํ ํธ๋ฆฌ(single state tree) ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ด ์งํฉ ๋ด์์ ํ์ฌ ์ํ๋ฅผ ์ฝ๊ฒ ์ฐพ์ ์ ์๋ค.
๋จ์ผ ์ํ ํธ๋ฆฌ(single state tree)
๋จ์ผ ์ํ ํธ๋ฆฌ๋, ์ฝ๊ฒ ๋งํด์ ํ๋์ ์ดํ๋ฆฌ์ผ์ด์
์ ํ๋์ store
๋ง ๊ฐ์ง๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
ํ๋์ store
๋ง ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ํ์ฌ state์ ์ํ(snapshot)๋ฅผ ์ฝ๊ฒ ์ฐพ์ ์ ์๋ค.
๋จ์ผ ์ํ ํธ๋ฆฌ๋ผ๋ ๋ง์ด ๋ค์ ์ด๋ ต๊ฒ ๋๊ปด์ง ์ ์์ผ๋ ์์ ๋ฅผ ํตํด ์์๋ณด์
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
count: 0
}
});
/src/store.js
<template>
<div>
This is A View
{{ count }}
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count
}
}
}
</script>
<style scoped>
</style>
/src/components/A.vue
<template>
<div>
This is B View
{{ count }}
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count
}
}
}
</script>
<style scoped>
</style>
B.vue
ํ์ฌ store
์ state
์ count
๋ผ๋ ์ํ๊ฐ ์๊ณ , ๊ทธ ์ํ๋ฅผ ๊ฐ๊ฐ A์ B ํ๋ฉด์์ ๋ถ๋ฌ์๋ค
๋ ๋ค 0์ผ๋ก count
๊ฐ ๋์ผํ๊ฒ ์ถ๋ ฅ๋๊ฑธ ๋ณผ ์ ์๋ค.
์ด์ ์ด ์ํ์์ A ์ปดํฌ๋ํธ์์ count
์ ๊ฐ์ ์ฆ๊ฐ์์ผ๋ณด์.+
๋ฒํผ์ ๋ง๋ค๊ณ ํด๋ฆญํ๋ฉด count
์ ๊ฐ์ด ์ฆ๊ฐ๋๋๋ก ํด๋ณด์๋ค.
<template>
<div>
This is A View
{{ count }}
<button @click="plus">+</button>
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count
}
},
methods: {
plus() {
this.$store.state.count++
}
}
}
</script>
<style scoped>
</style>
/src/components/A.vue
A ์ปดํฌ๋ํธ ๋ด์์ ์ฆ๊ฐ๋ฅผ ์์ผฐ๋๋ฐ, B ์ปดํฌ๋ํธ์ count
๋ ์ฆ๊ฐ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด๋ ๋จ์ผ ์ํ ํธ๋ฆฌ ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ๊ฒฐ๊ณผ์ด๋ค. ๋ง๊ทธ๋๋ก state
์ ์ํ๊ฐ ๋จ์ผ(์ ์ผ)ํ๋ค๋ ๊ฒ์ด๋ค.
store์ state ํ๋ฉด์ ์ถ๋ ฅ ์ํค๊ธฐ
์ ๋จ์ผ ์ํ ํธ๋ฆฌ ์์ ๋ฅผ ํตํด ์ด๋ฏธ state
๋ฅผ ํ๋ฉด์ ์ถ๋ ฅ์ํค๋ ์๋ฅผ ์ดํด๋ณด์์ง๋ง ํ๋ฒ ๋ ์ดํด๋ณด์.
๊ฐ๋จํ ์์ ๋ฅผ ํตํด ํ์ฌ state์ ์ํ๋ฅผ Vue ์ปดํฌ๋ํธ ํ๋ฉด์ ์ถ๋ ฅ์์ผ๋ณด๊ฒ ๋ค.
export const store = new Vuex.Store({
state: {
count: 0
},
});
/src/store.js
๋จผ์ store.js
ํ์ผ์ state.count
๋ฅผ ์ถ๊ฐํด์คฌ๋ค. store
์ count
์ํ๋ฅผ ๋ณด๊ดํ ๊ฒ์ด๋ค.
์ด ์ ์ฅ์์ ๋ณด๊ด๋ count
๋ฅผ Vue ์ปดํฌ๋ํธ์ ์ถ๋ ฅ์์ผ๋ณด๊ฒ ๋ค.store
์ count
๋ ์ดํ๋ฆฌ์ผ์ด์
์์ ๋จ ํ๋๋ง ์กด์ฌํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์,
๋ค๋ฅธ ์ปดํฌ๋ํธ์์ count
์ ์ํ๊ฐ ๋ณ์ด์์ผฐ๋ค๋ฉด ํ์ฌ ์ปดํฌ๋ํธ์์๋ ๊ทธ ๋ณํ๋ ์ํ๊ฐ ์ถ๋ ฅ๋์ด์ผ ํ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๊ธฐ ์ํด์ Vue์ computed
์์ฑ์ ํตํด store
์ state
๋ฅผ ์ถ๋ ฅํ๋ค.
<template>
<div>
{{ count }}
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count
}
}
}
</script>
<style scoped>
</style>
/src/components/Counter.vue
Counter.vue
๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ computed
์ this.$store.state.count
๋ฅผ ๋ฐํํ์ฌ ํ๋ฉด์ ์ถ๋ ฅ์์ผฐ๋ค.
0์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ถ๋ ฅ๋๊ฑธ ๋ณผ ์ ์์๋ค.๐
mapState
computed์ ์ ์ธ๋ ์ํ(state)๊ฐ ๋ง์ผ๋ฉด, ์ฝ๋๊ฐ ๋ฐ๋ณต์ ์ด๊ณ ์ฅํฉํด์ง ์ ์๋ค.
์๋ฅผ๋ค๋ฉด, ์ด๋ฐ์์ผ๋ก.
computed: {
count() {
return this.$store.state.count
},
age() {
return this.$store.state.age
},
isStudent() {
return this.$store.state.isStudent
}
}
this.$sotre.state
๊ฐ ๋ฐ๋ณต๋๋๊ฑธ ์ ์ ์๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Vuex๋ mapState ๋ผ๋ Helper๋ฅผ ์ ๊ณตํ๊ณ ์๋ค.
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// #1 ํ์ดํ ํจ์๋ก ๊ฐ์ ธ์ค๊ธฐ
count: state => state.count,
// #2 ๋ฌธ์์ด๋ก ๊ฐ์ ธ์ค๊ธฐ (`state => state.count`์ ๊ฐ๋ค.)
countAlias: 'count',
// #3 `this`๋ฅผ ์ฌ์ฉํ์ฌ ๋ก์ปฌ ์ํ์ ์ก์ธ์คํ๋ ค๋ฉด ์ผ๋ฐ์ ์ธ ํจ์๋ฅผ ์ฌ์ฉํด์ผํ๋ค
countPlusLocalState (state) {
return state.count + this.localCount
}
// #4 this.count๋ฅผ store.state.count์ ๋งคํํ๋ค.
'count'
})
}
mapState
๋ฅผ ํ์ฉํด ๋ฐ๋ณต๋๋ ์ฝ๋๋ฅผ ์์ ๊ณ state
๋ฅผ ๊น๋ํ๊ฒ ์ ์ํ ์ ์๋ค.mapState
๋ฅผ ๊ธฐ์กด ๋ก์ปฌ์ computed
์ ํจ๊ป ์ฌ์ฉํ๋ ค๋ฉด ๊ฐ์ฒด ์ ๊ฐ ์ฐ์ฐ์(Object Spread Operator) ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. ์ ๊ฐ๊ตฌ๋ฌธ์ด๋ผ๊ณ ๋ํ๋ค (...
)
computed: {
localComputed () { /* ... */ }, // ๊ธฐ์กด์ computed
...mapState({
// ...
})
}
๐ข ์ปดํฌ๋ํธ์๋ ์ฌ์ ํ ๋ก์ปฌ ์ํ(data())์ ์์ ์ ์๋ค.
Vuex๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํด์ ๋ชจ๋ ์ํ๋ฅผ store์ ๋ฃ์ ํ์๋ ์๋ค.
๐ getters
state
๋ฅผ ๊ณ์ฐํ ๊ฐ์ ์ฌ์ฉํด์ผํ ๋๊ฐ ์๋ค.
๋จ์ผ ์ํ ํธ๋ฆฌ ํํธ์์ ์ฐ๋ฆฐ count
๋ฅผ A ์ปดํฌ๋ํธ์์ ์ฆ๊ฐ์ํค๋ ์์ ๋ฅผ ์งํํ์๋ค.
์ด๋ ๊ฒ ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ์์ state
๋ฅผ ์ฆ๊ฐ์ํค๋ฉด ๋ฐ๋ณต ํธ์ถ์ด ์ฆ์์ ธ ๋นํจ์จ์ ์ธ ๋ก์ง์ด ๋๋ค.
getters
๋ ๊ทธ๋ฐ ๋ฌธ์ ์ ์ ํด๊ฒฐํด์ฃผ๋ ์์ฑ์ด๋ค.getters
๋ state
์ ๋ํ ๋ณ์ด๋ฅผ ๊ฐ ์ปดํฌ๋ํธ์์ ์งํํ๋๊ฒ ์๋๋ผ, Vuex์์ ๋ณ์ด๋ฅผ ์ํํ๊ณ ๊ฐ ์ปดํฌ๋ํธ์์ state
๋ฅผ ํธ์ถ๋ง ํ๋๋ก ํ๊ฒ ํ๋ค.
์์ ๋ก ์ดํด๋ณด์.
์นด์ดํธ๋ฅผ ์ฆ๊ฐ์ํค๋ ๋ก์ง์ Vuex ์ getters
์ ๋ฃ์ด๋ณผ ๊ฒ์ด๋ค.
export const store = new Vuex.Store({
state: {
count: 0
},
getters: {
increaseCount(state) {
return ++state.count;
}
}
});
/src/store.js
<template>
<div>
{{ count }}
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.getters.increaseCount;
}
}
}
</script>
<style scoped>
</style>
/src/components/Counter.vue
1 ์ด๋ผ๋ ์ฆ๊ฐ๋ ๊ฐ์ด ํ๋ฉด์ ์ถ๋ ฅ๋๋ ๊ฑธ ๋ณผ ์ ์๋ค.getters
๋ ์ด๋ฆ ๊ทธ๋๋ก ๋ฐํ๊ฐ์ด ์์ด์ผํ๋ค. ์ด ๋ฐํ๊ฐ์ state
๋ฟ๋ง ์๋๋ผ ๊ฐ์ getters
๊ฐ ๋ ์๋ ์๋ค.
getters: {
increaseCount:(state, getters) => {
return getters.getCurCount;
},
getCurCount: (state) => {
return state.count;
}
}
getters
๋ ๋ฐ๋ก ์ ๋ฌ์ธ์๋ฅผ ๋ฐ์ ์ ์๋ค. ๊ณง ์ดํด๋ณผ mutations
์์ ์ฐจ์ด์ ์ด๊ธฐ๋ ํ๋ค.
ํ์ง๋ง ํจ์๋ฅผ ๋ฐํํ์ฌ getters
์ ์ ๋ฌ์ธ์๋ฅผ ์ ๋ฌํ ์ ์๋ค.
getters ๋ ๋ฐ๋ก ์ ๋ฌ์ธ์๋ฅผ ๋ฐ์ ์ ์๋ค๊ณ ๋์ด์๋๋ฐ, increaseCount:(state, getters) => {}
์ฌ๊ธฐ์ ๋ณด์ด๋ state์ getters๋ ๋ฌด์์ผ๊น?
์ด๋ Vuex getters์ default ์ ๋ฌ ์ธ์๋ก, ๋ง๊ทธ๋๋ก ํ์ฌ state์ getters๋ฅผ ๋ํ๋ธ๋ค.
์ฒซ๋ฒ์งธ ์ ๋ฌ์ธ์๋ state, ๋๋ฒ์งธ๋ getters, ์ธ๋ฒ์งธ๋ rootState, ๋ค๋ฒ์งธ๋ rootGetters์ด๋ค.
(rootState ์ ๊ด๋ จํด์๋ modules ํํธ์์ ์์ธํ ๋ค๋ค๋ณธ๋ค.
state์ธ ์ ๋ฌ์ธ์๋ ์์ ์์๋ ์ ์ ์๋ฏ์ด ์ต์ ์ด๋ค.(์จ๋ ๋๊ณ ์จ์ฃผ์ง ์์๋ ๋๋...)
getters: {
increaseCount: (state) => (num) => {
return state.count + num;
},
}
// ๊ฐ์ ์๋ฏธ
increaseCount: (function (state) {
return function (num) {
return state.count + num;
};
});
mapGetters
state
ํํธ์์ ์ฝ๋๊ฐ ๋ฐ๋ณต๋๋ ๊ฑธ ๋ง๊ธฐ ์ํด mapState
๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํ์๋ค.getters
๋ ๋ง์ฐฌ๊ฐ์ง๋ก mapGetters
๋ฅผ ์ฌ์ฉํด ์ฝ๋์ ๋ฐ๋ณต์ ๋ง์ ์ ์๋ค.
(์ด ์ญ์, ๋ค๋ฅธ computed
์์ฑ๋ค๊ณผ ํจ๊ป ์ฐ๊ณ ์ถ๋ค๋ฉด ์ ๊ฐ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ฉด ๋๋ค.)
computed: {
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
getter
๋ฅผ ์๋์ ๊ฐ์ด ๋ค๋ฅธ ์ด๋ฆ์ผ๋ก ๋งคํํ ์๋ ์๋ค.store.getters.doneTodoxCount
๋ฅผ this.doneCount
๋ผ๋ ์ด๋ฆ์ผ๋ก ๋งคํํ ๊ฒฝ์ฐ์ด๋ค.
...mapGetters({
doneCount: 'doneTodosCount'
})
๐ mutations
mutations
๋ getters
์ ๋์ผํ๊ฒ state
์ ๊ฐ์ ๋ณํ ์ํฌ ๋ ์ฌ์ฉํ๋ค.
mutations
์ getters
์ ์ฐจ์ด์
mutations
๋ ์ ๋ฌ์ธ์๋ฅผ ๋ฐ์ ์ ์๋ค.getters
๋computed
์ ๋ฑ๋ก ํ์ง๋งmutations
๋methods
์ ๋ฑ๋กํ๋ค.
mutations
๋ ๋๊ธฐ์ ๋ก์ง์ ์ ์ํ๋ค๋ ํน์ง์ ๊ฐ์ง๊ณ ์๋ค.
๋๊ธฐ์ , ๋ง๊ทธ๋๋ก ์์ฐจ์ ์ผ๋ก ๋ณ์ด๊ฐ ์งํ๋๋ค๋ ๋ป์ด๋ค.
์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ํ๋์ ์ํ๋ฅผ ๋ณ์ด์ํจ๋ค๋ฉด ํ์ฌ state
๊ฐ ์ด๋ค์ง ์ถ์ ํ๊ธฐ ์ด๋ ค์ธ ๊ฒ์ด๋ค.
๊ทธ ๋, mutations
์ ์ ์ํ ์ํ๋ณ์ดํจ์๋ฅผ commit
์ ์ฌ์ฉํ์ฌ ๋ช
์์ ์ผ๋ก ํธ์ถํ๋ฉด ์ํ๋ฅผ ์ถ์ ํ ์ ์๋ค.
์๋ฅผ ํตํด ์์๋ณด์.
export const store = new Vuex.Store({
// ...
mutations: {
addCounter: function (state) {
return state.counter++;
}
}
});
/src/store.js
<template>
<div>
{{ count }}
<button @click="increaseCnt">+</button>
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count;
}
},
methods: {
increaseCnt() {
this.$store.commit('addCounter');
}
}
}
</script>
<style scoped>
</style>
Counter.vue
store.js
์ mutations
์ addCounter
๋ผ๊ณ count
๊ฐ์ ์ฆ๊ฐ์ํค๋ ๋ฉ์๋๋ฅผ ์ ์ํ๋ค.Counter.vue
์์ methods
๋ด์ commit
์ ์ฌ์ฉํ์ฌ addCounter
๋ฅผ ํธ์ถํ๋ค.
mutations
๋ฅผ ํตํด count
๊ฐ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ฆ๊ฐํ๋ ๊ฑธ ํ์ธํ ์ ์๋ค.
commit
์ type
์์ฑ์ ๊ฐ์ง ๊ฐ์ฒด๋ก mutations
์ ๋ฉ์๋๋ฅผ ๋ถ๋ฌ์ฌ ์๋ ์๋ค.
store.commit({
type: 'addCounter',
amount: 10 // ์ ๋ฌ์ธ์ (์๋์์ ์ค๋ช
)
})
mutations
๋ ๋๊ธฐ์ ๋ก์ง์ ๋ค๋ฃจ๊ธฐ ๋๋ฌธ์ this.$store.mutations.addCounter
๋ฑ์ผ๋ก ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์๋ค.
๋ฐ๋์ commit
์ ์ฌ์ฉํ์ฌ ๋ช
์์ ์ผ๋ก ํธ์ถํด state
์ ์ถ์ ์ด ๊ฐ๋ฅํ๊ฒ ํด์ผํ๋ค.
mutations์ ์ ๋ฌ ์ธ์
getters
์ mutations
์ ์ฐจ์ด์ ์ผ๋ก ์ ๋ฌ์ธ์๊ฐ ์๋ค๊ณ ํ์๋ค.mutations
์์ ์ด๋ป๊ฒ ์ ๋ฌ์ธ์๋ฅผ ๋ฐ์์ค๋ ์ง ์ดํด ๋ณด์.
// ...
mutations: {
increment (state, n) {
state.count += n
}
}
store.js
methods: {
increaseCnt(num) {
store.commit('increment', num)
}
}
Counter.vue
commit
์ ์ถ๊ฐ ์ ๋ฌ ์ธ์๋ฅผ ๋ถ์ฌ ์ ๋ฌ์ธ์๋ฅผ ๋๊ธธ ์ ์๋ค. ์ด ์ถ๊ฐ ์ ๋ฌ ์ธ์ ๋ถ๋ถ์ payload
๋ผ๊ณ ํ๋ค.payload
๋ ์๋์ ๊ฐ์ด ๊ฐ์ฒด ํํ๋ก ์ ๋ฌ ๋ ์๋ ์๋ค.
// ...
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.js
store.commit('increment', {
amount: 10
})
Counter.vue
mapMutations
mapState
, mapGetters
์ ๋ง์ฐฌ๊ฐ์ง๋ก mapMutations
๋ฅผ ์ฌ์ฉํ์ฌ mutations
๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ์ ๋ฆฌํ ์ ์๋ค.mapState
, mapGetters
์ ๋ค๋ฅธ ์ ์ methods
์ ์ ์ํด์คฌ๋ค๋ ์ ์ด๋ค.
import { mapMutations } from 'vuex'
methods: {
// Vuex ์ Mutations ๋ฉ์๋ ๋ช
๊ณผ App.vue ๋ฉ์๋ ๋ช
์ด ๋์ผํ ๋ [] ์ฌ์ฉ
...mapMutations([
'addCounter'
]),
// Vuex ์ Mutations ๋ฉ์๋ ๋ช
๊ณผ App.vue ๋ฉ์๋ ๋ช
์ ๋ค๋ฅด๊ฒ ๋งค์นญํ ๋ {} ์ฌ์ฉ
...mapMutations({
addCounter: 'addCounter' // ์ addCounter ๋ ํด๋น ์ปดํฌ๋ํธ์ ๋ฉ์๋๋ฅผ, ๋ค addCounter ๋ Vuex ์ Mutations ๋ฅผ ์๋ฏธ
})
}
mapMutations
๋ก ์ฌ์ฉํ๋ฏ๋ก์จ this.$store.commit('addCounter')
๋ฅผ this.addCounter
๋ก๋ง ์ธ์ ์๋ค.
๐ actions
mutations
๋ ๋๊ธฐ์ ๋ณ์ด๋ฅผ ๋ค๋ฃฌ๋ค๊ณ ํ์๋ค.
actions๋ ๊ทธ์ ๋ฐ๋๋ก, ๋น๋๊ธฐ์ ๋ณ์ด๋ฅผ ๋ค๋ฃจ๋ ์์ฑ์ด๋ค.
์ฃผ๋ก setTimeout()
์ด๋ ์๋ฒ์์ http ํต์ ์ฒ๋ฆฌ์ ๊ฐ์ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ฌ ํ์ด๋ฐ์ด ์์ธก๋์ง ์๋ ๋ก์ง์ actions
์ ์ ์ธํ๋ค.
mutations
์์ ์ํ์ ๋ณ์ด๋ฅผ ์ถ์ ํ๊ธฐ์ํด commit
์ ์ฌ์ฉํ๋ค๊ณ ํ์๋ค.actions
์ญ์ ๋น๋๊ธฐ์ ์ํ๋ฅผ ์ถ์ ํด์ผํ๊ธฐ ๋๋ฌธ์ commit
์ ์ฌ์ฉํ๋ค.
๊ฒฐ๊ตญ actions
๋ ์ ๋ฆฌํ์๋ฉด mutations
์ ๋ฉ์๋๋ฅผ actions
์ commit
์ผ๋ก ํธ์ถํ์ฌ ๋น๋๊ธฐ ๊ด๋ฆฌ๋ฅผ ํ๋ค๋ ๊ฒ์ด๋ค.
์๋ฅผ ๋ค์ด ์ดํด๋ณด์.
export const store = new Vuex.Store({
// ...
mutations: {
addCounter: function (state, payload) {
return state.counter++;
}
},
actions: {
addCounter: function (context) {
return context.commit('addCounter');
}
}
});
/src/store.js
actions
์์ commit
์ผ๋ก mutations
์ ๋ฉ์๋์ธ addCounter
๋ฅผ ํธ์ถํ ๊ฑธ ์ ์ ์๋ค.
์ฌ๊ธฐ์ ์ฃผ๋ชฉํด์ผํ ๊ฒ์ context
์ด๋ค. mutations
๋ getters
๋ state
๋ getters
, ๋ฅผ ๋ฐ์์์๋๋ฐ(ํน์ ์ ๋ฌ์ธ์ payload
), ์ด context
๋ ๋ฌด์์ผ๊น?
์ฝ์์ context
๋ฅผ ์ฐ์ด๋ณด๋, state
์ getters
๋ฅผ ๋ชจ๋ ํฌํจํ Object ์์ ์ ์ ์์๋ค.
์ด Object ๋ ํ์ฌ ์ ์ฅ์(store) ์ธ์คํด์ค์ ๊ฐ์ ๋ฉ์๋/ํ๋กํผํฐ ์ธํธ๋ฅผ ๋ํ๋ด๋ Vuex ์ปจํ
์คํธ ๊ฐ์ฒด์ด๋ค.context.getters
, context.state
๋ฅผ ์ฌ๋ฌ๋ฒ ์จ์ฃผ์ง ์๊ธฐ ์ํด์ ๊ตฌ์กฐ๋ถํดํ ๋น์ ์ฌ์ฉํ ์ ์๋ค.
addCounter: function ({commit}) {
return commit('addCounter');
}
๋ค์์ผ๋ก ์ปดํฌ๋ํธ methods
์์ actions
๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด์.
methods: {
increaseCnt() {
this.$store.dispatch('addCounter');
}
},
Conter.vue
mutations
์์ ์ปดํฌ๋ํธ methods
์์ commit
์ ์ฌ์ฉํ์ง๋ง, actions
๋ dispatch
๋ฅผ ์ฌ์ฉํ๋ค.mutations
์ ์ถ์ ๊ฐ๋ฅํ ์ํ๋ณ์ด๋ฅผ ๋ช
์์ ์ผ๋ก ํธ์ถํ๊ธฐ ์ํด commit
์ ์ฌ์ฉํ๋ค. ์ด commit
์ ์ฌ์ฉํ๋ ์ฆ์ ์ํ ๋ณ์ด๊ฐ ์คํ๋๋ค (๋๊ธฐ์ )dispatch
๋ ์ด๋ฌํ commit
์ ๋น๋๊ธฐ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๊ฒํ๋ค.action
๋ด์ ์ ์๋ commit
์ ํธ์ถ ์๊ธฐ๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์ง์ ํ๋ฏ๋ก์จ ๋ง์ด๋ค.
์๋ฅผ ๋ค์ด ์ดํด๋ด ์๋ค.
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
/src/store.js
methods: {
increaseCnt() {
this.$store.dispatch('incrementAsync');
}
}
Counter.vue
Counter ์ปดํฌ๋ํธ์์ dispatch
๋ฅผ ํตํด actions
์ incrementAsync
๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.incrementAsync
๋ฉ์๋ ๋ด๋ฅผ ์ดํด๋ณด๋,setTimeout
์ ํตํด ๋น๋๊ธฐ์ ์ผ๋ก commit
์ด ํธ์ถ๋๊ณ ์์๋ค.
์ด๋ก์จ ๋น๋๊ธฐ์ ์ํ ๋ณ์ด๊ฐ ๊ฐ๋ฅํ ๊ฒ์ด๋ค.
๋จ์ํ dispatch
๋ฅผ ์ฌ์ฉํ๋ค๊ณ ๋น๋๊ธฐ๊ฐ ๋๋ ๊ฒ์ด ์๋๋ผ actions
๋ฉ์๋ ๋ด์ ๋น๋๊ธฐ์ ์ผ๋ก commit
์ ํธ์ถํ๊ธฐ ๋๋ฌธ์ actions
๊ฐ ๋น๋๊ธฐ์ ๋ก์ง์ ๋ค๋ฃฌ๋ค๊ณ ํ๋ ๊ฒ์ด๋ค.
๊ฒฐ๊ตญ ์ฝ๊ฒ ๋งํ๋ฉด actions
๋ mutations
+ commit
์ ์งฌ๋ฝ์ด๋ผ๊ณ ํ ์ ์๋ค
actions
๋ mutations
๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ ๋ฌ์ธ์๋ฅผ ๋ฐ์ ์ ์๊ณ ,type
์์ฑ์ ํฌํจํ ๊ฐ์ฒด๋ฅผ ๋ฐ์์๋ ์๋ค.
// ํ์ด๋ก๋(์ ๋ฌ์ธ์)์ ํจ๊ป ๋์คํจ์น
store.dispatch('incrementAsync', {
amount: 10
})
// type์์ฑ์ ํฌํจํ ๊ฐ์ฒด์ ํจ๊ป ๋์คํจ์น
store.dispatch({
type: 'incrementAsync',
amount: 10
})
Promise/then, async/await
actions
๋ ๋น๋๊ธฐ์ ๋ก์ง์ ๋ค๋ฃฌ๋ค๊ณ ํ๋ค.
์ก์
์ด ์๋ฃ๋ ํ์ ๋ค์ ์ํ๋ณ์ด๊ฐ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
์ฐ๋ฆฌ๋ ๋ณดํต ์ธ์ ๋๋ ์ง ๋ชจ๋ฅด๋ ํ๋ก์ธ์ค์ ๋ค์ ํ์๋ฅผ ์ํด Promise
/then
, async
/await
๋ฅผ ์ฌ์ฉํ๋ค.
์์ ๋ฅผ ํตํด ์์๋ณด์
Promise/then
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
/src/store.js
store.dispatch('actionA').then(() => {
// ...
})
/src/components/Counter.vue
๋๋,
actions: {
// ...
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
/src/store.js
async/awiat
// getData() ๋ฐ getOtherData()๊ฐ Promise๋ฅผ ๋ฐํํ๋ค๊ณ ๊ฐ์
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // actionA๊ฐ ๋๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆผ
commit('gotOtherData', await getOtherData())
}
}
mapActions
actions
์ญ์ this.$store.dispatch('xxx')
์ ๋ฐ๋ณต์ ๋ง๊ธฐ ์ํด mapActions ๋ผ๋ ํฌํผ๋ฅผ ์ ๊ณตํ๋ค.
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment' // this.increment()์ this.$store.dispatch('increment')์ ๋งคํ
// mapActions๋ ํ์ด๋ก๋๋ฅผ ์ง์
'incrementBy' // this.incrementBy(amount)๋ฅผ this.$store.dispatch('incrementBy', amount)์ ๋งคํ
]),
...mapActions({
add: 'increment' // this.add()์ this.$store.dispatch('increment')์ ๋งคํ
})
}
}
๐ moodules
์ ์ฅ์์ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด ๊ด๋ฆฌ๊ฐ ํ๋ค์ด์ง ์๋ ์๋ค.
๊ทธ ๋, ์ฐ๋ฆฐ ์ ์ฅ์๋ฅผ ๋ชจ๋ํ ํ ์ ์๋ค.
๊ฐ๊ฐ์ state
, mutations
, getters
๋ฑ์ ํฌํจํ๋ ์ ์ฅ์ ์ฌ๋ฌ๊ฐ๋ก ๋๋ ์ ์๋ค๋ ์๋ฏธ์ด๋ค.
๐ ๋ชจ๋ํ๋?
ํน์ ๊ธฐ์ค์ ๋๊ณ , ๊ทธ ๊ธฐ์ค์ ๋ฐ๋ผ ๋ฆฌ์์ค๋ฅผ ๋จ์๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
์๋ฅผ ๋ค์ด, ๋๊ฐ์ ๋ฉ์๋ A ๋ฅผ ์ฌ๋ฌ ํ์ผ์์ ์ฐ๊ณ ์๋ค๊ณ ํ์.
์ด A ๋ฉ์๋๋ฅผ ์์ ํ๊ณ ์ถ๋ค๋ฉด, A ๋ฉ์๋๋ฅผ ์ฌ์ฉ ์ค์ธ ๋ชจ๋ ํ์ผ์ ๊ฐ์ ์ผ์ผ์ด ์์ ์ ํด์ค์ผํ๋ค.
A ๋ฉ์๋๋ฅผ ๊ด๋ฆฌํ๊ธฐ ๊ต์ฅํ ์ด๋ ค์์ง๋ค. ์ด ๋ ์ฐ๋ฆฐ ๋ชจ๋ํ๋ฅผ ํด์ค ์ ์๋ค.
A ๋ฉ์๋๋ฅผ Util.js ๋ฐ์์ ๊ณต์ฉํ ํ์ผ์ ํ๋ฒ๋ง ์ ์ํ ํ, A ๋ฉ์๋๊ฐ ํ์ํ๋ค๋ฉด Util.js์ A ๋ฉ์๋๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
ํ๋ง๋๋ก ์ด๋ค ๋ฆฌ์์ค(์ฌ๊ธฐ์ A ๋ฉ์๋)๋ฅผ ๋ฐ๋ก ๋ถ๋ฆฌํ์ฌ ๊ด๋ฆฌํ๋ ๊ฒ์ด๋ค.
์ ์ฅ์์ ๋ชจ๋ํ ๊ฐ์ ๊ฒฝ์ฐ,
state, getters, mutataions์ ํฌ๊ธฐ๊ฐ ๋๋ฌด ์ปค์ ธ์ ์ปดํฌ๋ํธ์์ ์ ์ฅ์๋ฅผ ํธ์ถํ ๋ ๋ฌด๋ฆฌ๊ฐ ์๊ธธ ์ ์๋ค.
๋๋ฌธ์ ์ด๋ค ์ฐ๋ฆฐ ๊ธฐ์ค์ ๋๊ณ ์ ์ฅ์๋ฅผ ์ชผ๊ฐ ๋ค, ํ์์์๋ง ์ชผ๊ฐ ์ผ๋ถ ์ ์ฅ์๋ง ํธ์ถํด์ ์ฐ๋ ๊ฒ์ด๋ค
์ด ์ญ์ ๋ถ๋ฆฌํด์ ๊ด๋ฆฌํ๋ค์ ๋ชจ๋ํ๋ฅผ ์๋ฏธํ๋ค.
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA'์ ์ํ
store.state.b // -> moduleB'์ ์ํ
์ ์ฝ๋๋ฅผ ๋ณด๋ฉด Store
์ธ์คํด์ค์ modules
๋ผ๋ ์์ฑ์ด ์๋ค.modules
๋ ๊ฐ๊ฐ์ state
, mutations
, getters
๋ฑ์ ํฌํจํ Object๋ฅผ ๋ด๊ณ ์๋ค.
์ ์ฅ์๋ฅผ ์ชผ๊ฐ์ด ๊ด๋ฆฌํ ์ ์๋ค๋ ๊ฑธ ์ ์ ์๋ค.
์ฐ๋ฆฌ๊ฐ ์์ ๋ก ๋ดค์๋ getters
์ mutations
์ ์ฒซ๋ฒ์งธ ์ธ์ state
๋ ๋ชจ๋ํ ๋์์ ๋,
๊ฐ ๋ชจ๋์ ์ง์ญ ์ํ๊ฐ ๋๋ค.actions
์ context
์์๋ context.state
๋ ์ง์ญ ์ํ์ด๋ค.
๋ฃจํธ์ ์ํ๋ context.rootState
๋ก ํ์๋๋ค. rootState
๋ getters
์ ์ธ๋ฒ์งธ ์ ๋ฌ์ธ์๋ก ๋
ธ์ถ๋๊ธฐ๋ ํ๋ค.
// actions
const moduleA = {
// ...
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
// getters
const moduleA = {
// ...
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
}
}
๋ค์์คํ์ด์ค
๋ชจ๋์ด ์ฌ๋ฌ๊ฐ ์กด์ฌํ ๋, ๋ชจ๋๊ฐ์ ์ถฉ๋์ด ๋ฐ์ํ ์ ์๋ค. ์๋ฅผ ๋ค๋ฉด, ๊ฐ๊ฐ ๋ค๋ฅธ ๋ชจ๋ ๋ด์ ๊ฐ์ ์ด๋ฆ์ด ๊ฐ์ state
, mutations
๊ฐ ์๋ ๊ฒฝ์ฐ ๋ฑ์์ ์ถฉ๋์ด ๋ฐ์ํ ์ ์๊ฒ ๋ค.
์ด๋ฌํ ์ถฉ๋์ ๋ฐฉ์งํ๊ธฐ ์ํด Vuex ๋ ๋ค์์คํ์ด์ค๋ผ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
๋ค์ ์คํ์ด์ค๋ ๋ชจ๋ ๋ด์ namespaced: true
๋ก ํ์ฑํ ํ ์ ์๋ค.
๋ค์์คํ์ด์ค๋, ์ปดํฌ๋ํธ์์ store
์์(getters
๋ฑ)๋ฅผ ํธ์ถ ํ ๋, ํด๋น store
๋ชจ๋์ ์ด๋ฆ์ ๋ถ์ฌ ํธ์ถํ๋ ๊ฒ์ด๋ค.
์ด ํธ์ถ์ด ์ด๋ค ์ ์ฅ์ ๋ชจ๋์์ ๋ถ๋ฌ์ค๋ ๊ฑด์ง ๋ช
์ํ์ฌ ์ถฉ๋์ ์๋ฐฉํ๋ ๊ฒ.
์์ ๋ก ์ดํด ๋ณด์.
export const store = new Vuex.Store({
modules: {
moduleA: {
// namespaced: true,
state: {
count: 0
},
mutations: {
addCounter: (state) => {
return state.count++;
}
}
},
moduleB: {
// namespaced: true,
state: {
count: 0
},
mutations: {
addCounter: (state) => {
return state.count++;
}
}
},
},
});
/src/store.js
namespaced
๋ฅผ ํ์ฑํํ์ง ์์ moduleA
์ moduleB
๋ฅผ ์ ์ํด์คฌ๋ค.
๋ ๋ชจ๋์ ๋ชจ๋ addCounter
๋ผ๋ ๊ฐ๊ฐ์ mutations
๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
A, B ์ปดํฌ๋ํธ๋ฅผ ๊ฐ๊ฐ ๋ง๋ค์ด ๊ฐ ์นด์ดํธ์ ์นด์ดํธ๋ฅผ ์ฆ๊ฐ์ํค๋ ๋ฒํผ์ ์ถ๋ ฅํด๋ดค๋ค.
<template>
<div>
{{ count }}
<button @click="increaseCnt">+</button>
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.moduleA.count;
}
},
methods: {
increaseCnt() {
console.log(this.$store.state.moduleA);
this.$store.commit('addCounter');
}
},
}
</script>
<style scoped>
</style>
/src/components/A.vue
<template>
<div>
{{ count }}
<button @click="increaseCnt">+</button>
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.moduleB.count;
}
},
methods: {
increaseCnt() {
this.$store.commit('addCounter');
}
},
}
</script>
<style scoped>
</style>
/src/components/B.vue
A.vue
๋ ๋ถ๋ช
ํ moduleA
์ count
๋ฅผ ์ถ๋ ฅํ๊ณ ์๊ณ ,B.vue
๋ ๋ถ๋ช
ํ moduleB
์ count
๋ฅผ ์ถ๋ ฅํ๊ณ ์๋ค.
ํ์ง๋ง A์ ํ๋ฌ์ค ๋ฒํผ์ ๋๋ ์ ๋, B ์ปดํฌ๋ํธ์ ์นด์ดํธ๊น์ง ํจ๊ป ์ฆ๊ฐํ๋ ๊ฑธ ๋ณผ ์ ์๋ค.
์๋ก ๋ค๋ฅธ ๋ชจ๋์ ์นด์ดํธ๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋๋ฐ๋ ๋ง์ด๋ค. ๐ฑ
์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ๋ชจ๋ ๋ด์ actions
, mutations
, getters
๋ ์ฌ์ ํ ์ ์ญ ๋ค์ ์คํ์ด์ค ์๋์ ๋ฑ๋ก๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ค. ๋ณธ์ธ์ด ์ด๋ค ๋ชจ๋ ์ถ์ ์ธ์ง ๋ชจ๋ฅด๋ ๊ฒ. ๋๋ฌธ์ ์ฌ๋ฌ ๋ชจ๋์ด ๋์ผํ ๋์์ ๋ณด์๋ ๊ฒ์ด๋ค.
์ด๋ฅผ ํด๊ฒฐํด์ฃผ๋๊ฒ ๋ค์ ์คํ์ด์ค์ด๋ค.
namespaced: true
์ ์ฃผ์์ ํ์ด ๋ค์์คํ์ด์ค๋ฅผ ํ์ฑํํ๊ณ ,
A, B ์ปดํฌ๋ํธ์ commit
์ ์๋์ ๊ฐ์ด ์์ ํด๋ดค๋ค.
// A.vue
this.$store.commit('moduleA/addCounter');
// B.vue
this.$store.commit('moduleB/addCounter');
๋ค์์คํ์ด์ค๋ก ๋ชจ๋์ด ๊ตฌ๋ถ๋์ด ์ฌ๋ฐ๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์จ๊ฑธ ํ์ธํ ์ ์์๋ค.
๋ค์์คํ์ด์ค ๋ชจ๋ ๋ด๋ถ์์ ์ ์ญ ์์ฐ ์ ๊ทผ
getters
์ ์ ๋ฌ์ธ์ ๋ถ๋ถ์์ ์ ๊น ์ธ๊ธ๋์๋๋ฐ,getters
์ actions
๋ ๊ฐ๊ฐ ๋ํดํธ ์ธ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
// getters
someGetter (state, getters, rootState, rootGetters) {
// ...
},
// actions (context ์ธ์ ๋ด์ ์๋ ์์ฑ๋ค)
someActions ({ dispatch, commit, getters, rootGetters }) {
// ...
}
์ด rootGetters
, ํน์ rootSetters
๋ฅผ ํตํด namespaced
๊ฐ ์ ์๋ ๋ชจ๋ ๋ด์์ ์ ์ญ ์์์ ์ ๊ทผํ ์ ์๋ค.
modules: {
foo: {
namespaced: true,
getters: {
// `getters`๋ ํด๋น ๋ชจ๋์ ์ง์ญํ๋ getters
// getters์ 4๋ฒ์งธ ์ธ์๋ฅผ ํตํด์ rootGetters ์ฌ์ฉ ๊ฐ๋ฅ
someGetter (state, getters, rootState, rootGetters) {
getters.someOtherGetter // -> 'foo/someOtherGetter'
rootGetters.someOtherGetter // -> 'someOtherGetter'
},
someOtherGetter: state => { ... }
},
actions: {
// ๋์คํจ์น์ ์ปค๋ฐ๋ ํด๋น ๋ชจ๋์ ์ง์ญํ๋ ๊ฒ
// ์ ์ญ ๋์คํจ์น/์ปค๋ฐ์ ์ํ `root` ์ต์
์ค์ ๊ฐ๋ฅ
someAction ({ dispatch, commit, getters, rootGetters }) {
getters.someGetter // -> 'foo/someGetter'
rootGetters.someGetter // -> 'someGetter'
dispatch('someOtherAction') // -> 'foo/someOtherAction'
dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
commit('someMutation') // -> 'foo/someMutation'
commit('someMutation', null, { root: true }) // -> 'someMutation'
},
someOtherAction (ctx, payload) { ... }
}
}
}
/src/store.js
์ ์ฝ๋์ root:true
๊ฐ ๋ณด์ด๋๊ฐ?
์ ์ญ actions
์ dispatch
ํ๊ฑฐ๋ mutations
๋ฅผ commit
ํ๋ ค๋ฉดdispatch
์ commit
์ 3๋ฒ์งธ ์ธ์์ { root: true }
๋ฅผ ์ ๋ฌํ๋ฉด ๋๋ค
๋ค์์คํ์ด์ค ๋ชจ๋ ๋ด๋ถ์์ ์ ์ญ ์ก์ ๋ฑ๋ก
๋ค์ ์คํ์ด์ค ๋ชจ๋์์ ์ ์ญ actions
๋ฅผ ๋ฑ๋กํ๋ ค๋ฉด root: true
๋ฅผ ํ์ํ๊ณ handler
ํจ์์ actions
๋ฅผ ์ ์ํ๋ฉด ๋๋ค.
actions: {
someOtherAction ({dispatch}) {
dispatch('someAction')
}
},
modules: {
foo: {
namespaced: true,
actions: {
someAction: {
root: true,
handler (namespacedContext, payload) { ... } // -> 'someAction'
}
}
}
}
/src/store.js
์ด๋ก์จ ์ ์ญ ์ก์
์ธ someOtherActions
์ ํธ์ถํ๋ฉด foo
๋ชจ๋์ ์ ์๋someAction
์ด ์คํ๋ ๊ฒ์ด๋ค.
ํฌํผ์์ ๋ค์์คํ์ด์ค ๋ฐ์ธ๋ฉ
ํฌํผ์๋ mapState
, mapGetters
, mapActions
, mapMutations
๊ฐ ์๋ค๊ณ ํ์๋ค.
ํฌํผ์์ ๋ค์์คํ์ด์ค ๋ชจ๋์ ์ปดํฌ๋ํธ์ ๋ฐ์ธ๋ฉํ ๋ ์กฐ๊ธ ์ฅํฉํ๊ฒ ๋ ์ ์๋ค.
computed: {
...mapState({
a: state => state.some.nested.module.a,
b: state => state.some.nested.module.b
})
},
methods: {
...mapActions([
'some/nested/module/foo', // -> this['some/nested/module/foo']()
'some/nested/module/bar' // -> this['some/nested/module/bar']()
])
}
์ค์ฒฉ๋ ๋ชจ๋์ ๋ค์์คํ์ด์ค ๋๋ฌธ์ ๊ฐ์ ์ฝ๋๊ฐ ๋ฐ๋ณต๋๊ณ ๊ธธ์ด์ง๊ฑธ ๋ณผ ์ ์๋ค.
์ด๋ ๋ชจ๋์ ๋ค์์คํ์ด์ค ๋ฌธ์์ด์ ํฌํผ์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ์ฌ ๊ฐ๊ฒฐํ ํ ์ ์๋ค.
computed: {
...mapState('some/nested/module', {
a: state => state.a,
b: state => state.b
})
},
methods: {
...mapActions('some/nested/module', [
'foo', // -> this.foo()
'bar' // -> this.bar()
])
}
๋ํ createNamespacedHelpers๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์์คํ์ด์ค ํฌํผ๋ฅผ ์์ฑํ ์ ์๋ค.
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
export default {
computed: {
// `some/nested/module`์์ ์ฐพ์
...mapState({
a: state => state.a,
b: state => state.b
})
},
methods: {
// `some/nested/module`์์ ์ฐพ์
...mapActions([
'foo',
'bar'
])
}
}
๋์ ๋ชจ๋ ๋ฑ๋ก
store.registerModule ๋ฉ์๋๋ก ์ ์ฅ์(store)๊ฐ ๋ฑ๋ก๋ ํ์๋ ๋ชจ๋์ ๋ฑ๋กํ ์ ์๋ค.
store.registerModule('myModule', {
// ...
})
// `nested/myModule` ์ค์ฒฉ ๋ชจ๋ ๋ฑ๋ก
store.registerModule(['nested', 'myModule'], {
// ...
})
store.unregisterModule(moduleName) ๋ก ๋์ ์ผ๋ก ๋ฑ๋ก๋ ๋ชจ๋์ ์ ๊ฑฐํ ์๋ ์๋ค.
์ ์ ๋ชจ๋์ ์ ๊ฑฐํ ์ ์๋ค
์ด๋ก์จ Vuex ์ ๋ํ ๊ฐ๋ ๊ณผ ์์ ์ ๋ํด ๋ชจ๋ ์์๋ดค๋ค!
๋๊ธ๊ณผ ํผ๋๋ฐฑ์ ์ธ์ ๋ ํ์ํฉ๋๋ค...