ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Vuex 핵심 컨셉(5) - 모듈(module)
    Vue/Vuex 2021. 7. 2. 11:35
    • 단일 상태 트리를 사용하기 때문에 어플리케이션의 하나의 큰 객체 안에 포함
    • 규모가 커짐에 따라 저장소는 매우 비대해질 수 있다.
    • 이를 위해 Vuex는 Store를 모듈로 나눌 수 있다.
    • 각 모듈은 자체 상태, 변이, 액션, getters 및 중첩된 모듈을 포함할 수 있다.
    const moduleA = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... }
    }
    
    const store = createStore({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    
    store.state.a // -> `moduleA`'s state
    store.state.b // -> `moduleB`'s state

     

    - 모듈 로컬 상태

    • 모듈의 변이 및 getters의 첫번째 인자는 모듈의 지역 상태(state)를 받는다.
    const moduleA = {
      state: () => ({
        count: 0
      }),
      mutations: {
        increment (state) {
          // state는 지역 모듈 상태 입니다
          state.count++
        }
      },
    
      getters: {
        doubleCount (state) {
          return state.count * 2
        }
      }
    }
    • 모듈의 액션에서는 context.state는 지역 상태이고 context.rootState는 루트 상태이다.
    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
        }
      }
    }

     

    - 네임 스페이스

    • 기본적으로 모듈 내의 액션,변이 및 getters는 여전히 전역 네임 스페이스에 등록된다.
      여러 모듈이 동일한 변이/액션 유형에 반응 할 수 있다.
    • 모듈이 독립적이거나 재사용되기를 원한다면 namespaced: true 설정
      해당 모듈의 모든 getter, 액션/변이는 자동으로 등록된 모듈의 경로를 기반으로 네임스페이스 지정됨
    • 네임 스페이스의 getter와 액션은 지역화된 getters, dispatch, commit을 받는다.
      즉, 동일한 모듈 안에서 접두어 없이 모듈을 사용할 수 있다.
    • 네임 스페이스 옵션 값을 바꾸어도 모듈 내부의 코드에는 영향을 미치지 않는다.
    const store = createStore({
      modules: {
        account: {
          namespaced: true,
    
          // module assets
          state: () => ({ ... }), // module state is already nested and not affected by namespace option
          getters: {
            isAdmin () { ... } // -> getters['account/isAdmin']
          },
          actions: {
            login () { ... } // -> dispatch('account/login')
          },
          mutations: {
            login () { ... } // -> commit('account/login')
          },
    
          // nested modules
          modules: {
            // inherits the namespace from parent module
            myPage: {
              state: () => ({ ... }),
              getters: {
                profile () { ... } // -> getters['account/profile']
              }
            },
    
            // further nest the namespace
            posts: {
              namespaced: true,
    
              state: () => ({ ... }),
              getters: {
                popular () { ... } // -> getters['account/posts/popular']
              }
            }
          }
        }
      }
    })

     

    - 네임 스페이스 모듈 내부에서 전역 접근

    • 전역 상태나 getter를 사용하고자 한다면, rootStaterootGetters가 getter 함수의 3번째와 4번째 인자로 전달되고, action 함수에 전달된 context 객체의 속성으로도 노출된다.
    • 전역 스페이스의 액션을 dispatch하거나 변이를 커밋하려면 dispatchcommit에 3번째 인자로 { root: true }를 전달하면 된다.
    modules: {
      foo: {
        namespaced: true,
    
        getters: {
          // `getters` is localized to this module's getters
          // you can use rootGetters via 4th argument of getters
          someGetter (state, getters, rootState, rootGetters) {
            getters.someOtherGetter // -> 'foo/someOtherGetter'
            rootGetters.someOtherGetter // -> 'someOtherGetter'
            rootGetters['bar/someOtherGetter'] // -> 'bar/someOtherGetter'
          },
          someOtherGetter: state => { ... }
        },
    
        actions: {
          // dispatch and commit are also localized for this module
          // they will accept `root` option for the root dispatch/commit
          someAction ({ dispatch, commit, getters, rootGetters }) {
            getters.someGetter // -> 'foo/someGetter'
            rootGetters.someGetter // -> 'someGetter'
            rootGetters['bar/someGetter'] // -> 'bar/someGetter'
    
            dispatch('someOtherAction') // -> 'foo/someOtherAction'
            dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
    
            commit('someMutation') // -> 'foo/someMutation'
            commit('someMutation', null, { root: true }) // -> 'someMutation'
          },
          someOtherAction (ctx, payload) { ... }
        }
      }
    }

     

    - 네임 스페이스 모듈에서 전역 액션 등록

    • 네임 스페이스 모듈에서 전역 액션을 등록하려면, root: true를 표시하고 handler 함수에 액션을 정의
    {
      actions: {
        someOtherAction ({dispatch}) {
          dispatch('someAction')
        }
      },
      modules: {
        foo: {
          namespaced: true,
    
          actions: {
            someAction: {
              root: true,
              handler (namespacedContext, payload) { ... } // -> 'someAction'
            }
          }
        }
      }
    }

     

    - 동적 모듈 등록

    • store.registerModule 메서드로 Store가 생성된 후에 모듈을 등록 할 수 있다.
    import { createStore } from 'vuex'
    
    const store = createStore({ /* options */ })
    
    // register a module `myModule`
    store.registerModule('myModule', {
      // ...
    })
    
    // register a nested module `nested/myModule`
    store.registerModule(['nested', 'myModule'], {
      // ...
    })
    • 모듈의 상태는 store.state.myModulestore.state.nested.myModule 로 노출 된다.
    • 동적 모듈 등록을 사용하면 다른 Vue 플러그인도 에플리케이션의 Store에 모듈을 연결하여 상태 관리에 Vuex를 활용할 수 있다.
      • vuex-router-sync 라이브러리는 동적으로 연결된 모듈에서 에플리케이션의 라우트 상태를 관리하여 vue-router와 vuex를 통합한다.

    • store.unregisterModule(moduleName)을 사용하여 동적으로 등록 된 모듈을 제거할 수 있다.
      단, 정적 모듈(저장소 생성시 선언 됨)은 제거할 수 없다.
    • SSR 앱에서 상태를 유지하는 것처럼 새 모듈을 등록할 때 preserveState 옵션을 사용하여 이전 상태를 유지할 수 있다.
      • store.registerModule('a', module, { preserveState: true })

     

    - 모듈 재사용

    • 한 모듈에서 여러 인스턴스를 생성해야 하는 경우 발생
      • 동일 모듈을 사용하는 여러 저장소 생성
        • SSR에서 싱글톤 상태 피하기에서 runInNewContext 옵션이 false나 once일 때

      • 동일 모듈을 동일 저장소에 여러번 등록

    • 일반 객체를 사용하여 모듈의 상태를 선언하면 상태 객체가 참조에 의해 공유되고 변이될 때 교차 저장소/모듈의 상태 오염을 일으킨다.
    • 함수를 사용하여 모듈 상태를 선언
    const MyReusableModule = {
      state: () => ({
        foo: 'bar'
      }),
      // 변이, 액션, getters...
    }

     

    [ 참고자료 ]

    https://next.vuex.vuejs.org/guide/modules.html

     

    Modules | Vuex

    Modules Due to using a single state tree, all states of our application are contained inside one big object. However, as our application grows in scale, the store can get really bloated. To help with that, Vuex allows us to divide our store into modules. E

    next.vuex.vuejs.org

     

    'Vue > Vuex' 카테고리의 다른 글

    Vuex 핵심 컨셉(4) - 액션(actions)  (0) 2021.07.01
    Vuex 핵심 컨셉(3) - 변이(mutations)  (0) 2021.07.01
    Vuex 핵심 컨셉(2) - Getters  (0) 2021.07.01
    Vuex 핵심 컨셉(1) - 상태  (0) 2021.07.01
    Vuex 시작하기(3) - Store  (0) 2021.06.30

    댓글

Designed by Tistory.