[Vue] Vuex Binding Helper / modules

문지은·2023년 6월 18일
0

Vue

목록 보기
9/15
post-thumbnail

Vuex Binding Helper

  • Vuex store의 state, mutations, actions 등을 간단하게 사용할 수 있도록 만들어진 헬퍼 함수
  • mapState, mapActions 와 같은 형식으로 사용
  • 사용하기 위해서는 import 받아와야 함
import { mapState, mapActions } from 'vuex'

mapState

  • Vuex store의 상태를 컴포넌트의 데이터에 매핑할 때 사용
  • 객체 혹은 배열 형태로 상태를 매핑하여 사용 할 수 있음

객체 형태로 매핑

  • mapState를 import
  • Spread operator를 사용하여 mapState를 전개
  • mapState 내부에 불러오고자 하는 값을 정의
  • 화살표 함수를 사용하여 message key에 state의 message 값을 할당
    • key 값은 컴포넌트에서 사용하고자 하는 다른 이름으로 변경하여 사용 할 수 있음
// App.vue

<template>
  <div id="app">
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
	...
  // 객체 형태로 매핑
  ...mapState({
     msg: state => state.message
   }),
  },
},
}
</script>

배열 형태로 매핑

  • mapState를 import
  • Spread operator를 사용하여 mapState를 전개
  • vuex store의 상태 중, 불러오고자 하는 대상을 배열의 원소로 정의
// App.vue

<template>
  <div id="app">
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
import { mapState } from 'vuex'

export default {
	...
  // 배열 형태로 매핑
  ...mapState(['message']),
  },
},
}
</script>

mapActions

  • 컴포넌트에서 this.$store.dispatch() 를 호출하는 대신, 액션 메서드를 직접 호출하여 사용 할 수 있음
  • mapState와 같이 객체 혹은 배열 형태로 매핑가능

배열 형태로 매핑

  • mapState와 동일한 형식으로 사용
  • 단, 이 경우 changeMessage에 넘겨주어야 할 inputData를 changeMessage 호출 시 인자로 직접 값을 넘겨주어야 함
<template>
	<div id="app">
		<h1>{{ message }}</h1>
		<input
		type="text"
		@keyup.enter="changeMessage(inputData)"
		v-model="inputData“>
	</div>
</template>

<script>
import { mapActions } from 'vuex’

export default {
	**...**
	methods: {
		...mapActions(['changeMessage'])
	},
}
</script>
  • 정상 작동하지만 input 제출 후 초기화 되지 않음

객체 형태로 매핑

  • Actions의 changeMessage를 actionsChangeMessage에 매핑
  • this.actionsChangeMessage 형식으로 사용
  • payload를 넘겨주거나 추가적인 로직 작성 가능
<template>
	<div id="app">
		<input
		type="text“
		@keyup.enter="onSubmit"
		v-model="inputData“>
	</div>
</template>

<script>
	import { mapActions } from 'vuex'
	export default {
		...
		methods: {
			...mapActions({
				actionsChangeMessage: 'changeMessage'
			}),
			onSubmit() {
				const newMessage = this.inputData
				this.actionsChangeMessage(newMessage)
				this.inputData = ''
			}
		}
	}
</script>
  • input 제출 후 초기화 되는 것 확인

mapGetters

  • mapState, mapActions와 동일한 방식으로 사용가능
<template>
	<div id="app">
		<h1>길이 {{ messageLength }}의 메시지 {{ message }}를 입력받음</h1>
		<h3>x2 : {{ doubleLength }}</h3>
	</div>
</template>

<script>
	import { mapGetters } from 'vuex'

	export default {
		...
		computed: {
			...mapGetters(['messageLength', 'doubleLength'])
		},
	}
</script>

[참고]

  • 상황에 따라서는 배열과 객체 형태로 각각 매핑하여 사용 할 수 있음
<template>
	<div id="app">
		<h1>{{ age }} {{ message }}</h1>
	</div>
</template>

<script>
	import { mapState } from 'vuex'
	export default {
		...
		computed: {
			...mapState(['message']),
			...mapState({
				age: state => state.age
			})
		},
	}
</script>

modules

  • Vuex store를 여러 파일로 나눠서 관리 할 수 있게 해 주는 기능
  • Vuex store와 동일한 구성을 가진 별도의 객체를 정의하여 modules 옵션에 작성한 객체를 추가하여 사용
  • 별개의 .js 파일에 정의하고 import 하는 방식으로도 사용가능
  • Store의 가독성을 향상시킬 수 있음

Vuex에 적용하기

  • 별도의 js 파일에 객체 정의
// store/modules/myModule.js

const myModule = {
    state: {
        age: 30
    },
    mutations: {
        INCREMENT_AGE(state) {
            state.age += 1
        }
    },
    actions: {
        incrementAge(context) {
            context.commit('INCREMENT_AGE')
        }
    }
}

export default myModule
  • 만약 모듈안의 Vuex 인스턴스를 각각 정의할 경우, export 할 때 반드시 중괄호와 함께 적어주어야 한다.
const state = {
}
const getters = {
}
const mutations = {
}
const actions = {
}

export default {
  state,
  getters,
  mutations,
  actions,
}
  • 정의한 js 파일의 객체를 import
    • Store의 modules 옵션에 추가
import Vue from 'vue'
import Vuex from 'vuex'
import myModule from './modules/myModule'

Vue.use(Vuex)

export default new Vuex.Store({ 
	modules: {
		myModule
	}
})
  • 클릭하면 age가 올라가게 하는 버튼 작성하기
<template>
  <div id="app">
    <h1>길이 {{ messageLength }}의 메시지 {{ message }}를 입력받음</h1>
    <h3>x2 : {{ doubleLength }}</h3>
    <input type="text" @keyup.enter="onSubmit" v-model="inputData">

    <h1>{{ age }}</h1>
    <button @click="upage">age up</button>
    
  </div>
</template>

<script>
import { mapState, mapActions, mapGetters } from 'vuex'

export default {
  name: 'App',
  components: {
  },

  created() {
    this.$store.dispatch('loadMessage')
  },

  computed: {

    // 둘 다 사용 가능!
    // mapState - 배열 형태로 매핑
    // ...mapState(['age']),

    // mapState - 객체 형태로 매핑
    ...mapState({
      msg: state => state.message,
      age: state => state.myModule.age,
    }),

    // mapGetters 매핑
    ...mapGetters(['messageLength', 'doubleLength'])

  },
  data() {
    return {
      inputData: null,
    }
  },
  methods: {

    // mapActions - 배열 형태로 매핑
    // ...mapActions(['changeMessage']),

    // mapActions - 객체 형태로 매핑
    ...mapActions({
      actionsChangeMessage: 'changeMessage',
    }),

    onSubmit() {
      const newMessage = this.inputData
      this.actionsChangeMessage(newMessage)
      this.inputData = null
    },

    upage() {
       this.$store.dispatch('incrementAge')
    }
  },
}
</script>
  • maActions 매핑하기
<template>
  <div id="app">
    <h1>길이 {{ messageLength }}의 메시지 {{ message }}를 입력받음</h1>
    <h3>x2 : {{ doubleLength }}</h3>
    <!-- mapActions 배열 형태로 매핑 -->
    <!-- <input type="text" @keyup.enter="changeMessage(inputData)" v-model="inputData"> -->
    <!-- mapActions 객체 형태로 매핑 -->
    <input type="text" @keyup.enter="onSubmit" v-model="inputData">

    <h1>{{ age }}</h1>
    <button @click="upage">age up</button>
    
  </div>
</template>

<script>
import { mapState, mapActions, mapGetters } from 'vuex'

export default {
  name: 'App',
  components: {
  },

  created() {
    this.$store.dispatch('loadMessage')
  },

  computed: {

    // 둘 다 사용 가능!
    // mapState - 배열 형태로 매핑
    // ...mapState(['age']),

    // mapState - 객체 형태로 매핑
    ...mapState({
      msg: state => state.message,
      age: state => state.myModule.age,
    }),

    // mapGetters 매핑
    ...mapGetters(['messageLength', 'doubleLength'])

  },
  data() {
    return {
      inputData: null,
    }
  },
  methods: {

    // mapActions - 배열 형태로 매핑
    // ...mapActions(['changeMessage']),

    // mapActions - 객체 형태로 매핑
    ...mapActions({
      actionsChangeMessage: 'changeMessage',
      upage: 'incrementAge'
    }),
    onSubmit() {
      const newMessage = this.inputData
      this.actionsChangeMessage(newMessage)
      this.inputData = null
    },
    // upage() {
    //   this.$store.dispatch('incrementAge')
    // }
  },
}
</script>
profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈

0개의 댓글