vuex

jude·2022년 4월 17일
0

vue

목록 보기
14/14
post-thumbnail

vuex

  • vuex는 중앙 집중식 데이터 관리를 위한 vue 공식 플러그인이다.
  • 프로젝트 구조가 복잡해지면 여러 컴포넌트들간에 props, emit, provide, inject 등으로만 데이터를 주고받기엔 너무 복잡해지기 때문에 이럴 경우 vuex를 사용한다.
  • 보편적으로 이 중앙 집중식 데이터 저장소를 store 라고 사용한다. (다른 이름으로 써도 상관없지만 용도에 맞는 적절한 네이밍이 좋다)

vuex 구성

  • createStorevuex에서 꺼내와서 사용
    • state - 일반적인 데이터들을 선언
    • getters - state의 데이터를 활용해서 새로운 값을 만들어낼 때 사용 (computed 처럼 함수로 만들고 값을 반환)
      • 매개변수로 state를 받아 사용할 수 있다.
    • mutations - state 값을 변경할 때 사용
      • 첫번째 매개변수로 state를 받아 사용할 수 있다.
      • 2번째 매개변수로는 함수 호출시 인수를 받을 수 있다.
    • actions - 비동기 호출 관련 함수를 사용
      • 첫번째 매개변수로 context 객체를 받을 수 있다.
        • context 객체는 state, getters, commit(mutations를 호출) 을 꺼내 사용할 수 있다.
      • 2번째 매개변수로는 함수 호출시 인수를 받을 수 있다.
  • 여러 컴포넌트들에서 데이터의 수정, 변경 등을 구현할 시 전체적인 데이터 관리에 어려움이 생기기 때문에 vuex에서는 이러한 구조적인 제한을 통해 유지보수를 용이하게 관리할 수 있다.
  • 아래와 같이 하나의 파일에서 모든 데이터를 관리할 수도 있지만, 되도록 데이터들의 성격에 맞게 모듈화를 하여 사용하는 것을 권장한다.
// ./store/index.js

import { createStore } from 'vuex'

export default createStore({
  // 데이터
  state: () => ({
  	count: 1
  }),
  // computed
  getters: {
  	doubleCount(state) {
      return state.count * 2
    }
  },
  // methods (데이터의 변경)
  mutations: {
  	increment(state, payload) {
      state.count++
    }
  },
  // 비동기 methods
  actions: {
  	searchMovie(context, payload) {
    },
    fetchMovie({ state, getters, commit, dispatch }, payload) {
	}
  }
})
  • 컴포넌트에서 store의 데이터를 사용하려면 this.$store.state 와 같은 식으로 사용할 수 있다.
created() {
  console.log(this.$store.state.count) // 1
  console.log(this.$store.getters.doubleCount) // 2
  console.log(this.$store.commit('increment')) // count : 3 (mutations 호출)
  this.$store.dispatch('searchMovie') // 비동기 함수 호출 (actions 호출)
}

// 또는

computed: {
  count() {
    return this.$store.state.count
  },
  doubleCount() {
    return this.$store.getters.doubleCount
  }
}

데이터의 성격에 맞게 모듈화

// ./store/index.js

import { createStore } from 'vuex'
import movie from './movie' // 모듈 1
import about from './about' // 모듈 2

export default createStore({
  modules: {
    movie,
    about
  }
})
  • namespaced 속성을 true 값으로 하면 해당 파일 이름으로 모듈 네임이 지정된다.
// movie.js

export default {
  namespaced: true,
  state: () => ({}), // 객체를 반환하는 함수
  getters: {},
  mutations: {},
  actions: {}
}
  • 모듈 데이터를 컴포넌트에서 사용할 시 아래와 같이 모듈 이름을 추가로 지정하여 사용한다.
created() {
  console.log(this.$store.state.movie.count) // 1
  console.log(this.$store.getters['movie/doubleCount']) // 2
  console.log(this.$store.commit('movie/increment')) // 3
}

// 또는

computed: {
  count() {
    return this.$store.state.movie.count
  },
  doubleCount() {
    return this.$store.getters.movie.doubleCount
  }
}

Helper

  • store의 데이터를 컴포넌트에서 사용할 시 중복되는 코드가 많고 코드량이 늘어나는 것을 Helper 함수로 보완할 수 있다.
  • mapState, mapGetters는 사용방법이 동일하다
  • mapMutations, mapActions 역시 사용방법이 같고 데이터명을 다른 이름으로 대체가 가능하다.
import { mapState, mapGetters, mapMutations } from 'vuex'

export default {
  // 모듈 없이 사용할 경우
  computed: {
    ...mapState([
      'count',
    ]),
    ...mapGetters([
      'doubleCount'
    ])
  }
  
  
  // 모듈을 사용할 경우
  computed: {
    ...mapState('movie', [ // 모듈 이름을 문자 데이터로 작성
      'count',
    ]),
    ...mapGetters('movie', [
      'doubleCount'
    ])
  }
  
  // mapMutations
  methods: {
    ...mapMutations([
      'increment', // map `this.increment()` to `this.$store.commit('increment')`

      // `mapMutations` also supports payloads:
      'incrementBy' // map `this.incrementBy(amount)` to `this.$store.commit('incrementBy', amount)`
	}),
      
    ...mapMutations({
      add: 'increment' // map `this.add()` to `this.$store.commit('increment')`
    })
  }
}

main.js에 연결

// main.js

import { createApp } from 'vue'
import App from './App'
import router from './routes'
import store from './store' // store 불러오기

createApp(App)
  .use(router)
  .use(store) // store 연결
  .mount('body')
profile
UI 화면 만드는걸 좋아하는 UI개발자입니다. 프론트엔드 개발 공부 중입니다. 공부한 부분을 블로그로 간략히 정리하는 편입니다.

0개의 댓글