본문 바로가기

3.구현/HTML5&Javascript

[vue2] vuex 사용하기

vue.js에서 공통으로 사용할 저장소가 필요할 때가 있다. 그때 vuex을 사용하면 된다.

들어가기

vuex은 vue.js에서 사용하는 중앙집중 상태관리 패턴 라이브러리이다. 상태라는 부분은 data에 해당하는 부분이라고 보면된다. 이런 상태가 화면이나 입력 처리에 사용된다. 이런 상태를 여러 컴포넌트가 같이 사용하거나 중첩이 많이된 컴포넌트 하위에 데이터를 전달할 경우 컴포넌트들 간에 넘겨주고 받아야하는 작업이 매번 발생하게 된다. 이를 한 곳에 관리하게 된다면 컴포넌트 사용할 때에 이런 상태 연결관계를 걱정할 필요가 없게 된다.

작성자: ospace114@empal.com, http://ospace.tistory.com/

vuex 사용시 주의점은 ES2015 문법을 사용해야한다.

vuex 생성

const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        increment(state) {
            state.count++;
        }
    }
});

vuex 사용하기

store.commit('increment'); //set
console.log(store.state.count); //get

전역으로 접근하기

include store from '@/store';
…
new Vue({
    …
    store,
}).$mount('#app');

사용예

console.log(this.$store.state.count);

컴포넌트에서 접근

computed 사용

<div>{{count}}</div>
….
computed: {
    count() {
        return this.$store.state.count;
    }
}

mapState Helper

import { mapState } from 'vuex';

export default  {
//…
    computed: mapState({
        count: state => state.count,
        countAlias: 'count',
    })
}

속성이름과 하위 트리이름이 같을 경우는 다음처럼 간략하게 사용 가능하다.

computed: mapState([
    'count'
])

객체 전개 연산자(object spread operator)을 사용하게 한꺼번에 추가해보자.

computed: {
    localComputed() { },
    …mapState([
        …
    ])
}

Getter 사용

데이터 가공해서 획득하는 경우 getter 정의해서 공통으로 사용할 수 있다.

const store = new Vuex.Store({
    state: {
        ...
    },
    getters: {
        filteredFoo: state => {
            return state.foo.filter(…);
        }
    }
});

사용예

console.log( store.getters.filteredFoo );

getters에서 두번째 인자로 다른 getters 받음. 원하는 getter을 호출해서 사용가능.

getters: {
    filteredFooCount: (state, getters) => {
        return getters.filteredFoo.length;
    }
}

사용예

console.log( store.getters.filteredFooCount );

함수를 파라미터로 넘겨서 호출

getters: {
    filteredFooBy: (state) => (val) => {
        return state.foo.find( f => f === val );
    }
}

mapGetter Helpper

computed: {
    …mapGetters([
        'filteredFoo',
        'filteredFooCount',
    ])
}

다른 이름으로 변경해서 등록

computed: {
    …mapGetters({
        fooCount: 'filteredFooCount',
    })
}

mutations 사용

state의 값을 변경할 때 사용하는 유일한 방법.
mutation 값 수정은 반드시 동기적으로 처리.

mutation: {
    addCount (state, val) {
        state.count += val;
    }
}

사용예

store.commit('addCount', 10);

const 사용

const FOO = 'FOO';

const store = new Vuex.Store({
    state: { … },
    mutations: {
        [FOO] (state) {
            //…
        }
    }
});

mapMutations Helpper

methods: {
    …MapMutations([
        'increment'
    ]),
    …MapMutations({
        add: 'increment'
    }),
}

Action

mutation과 비슷한 작업. mutation을 사용해서 값 수정.
비동기 작업 포함 가능.

const store = new Vuex.Store({
    state: { … },
    mutations: {
        increment(state) {
            state.count++;
        }
    },
    actions: {
        increment (context) {
            context.commit('increment');
        }
    },
});

사용예

store.dispatch('increment');

비동기사용

actions: {
    incrementAsync: ({commit}) {
        setTimeout(_=> commit('increment'), 1000);
    }
}

action 활용

actions: {
    checkout({ commit, state }, products) {
        const cartItems = […state.cart.added];
        // 결재요청후 장바구니 비움
        commit(types.CHECKOUT_REQ);

        shop.buyProducts(
            products,
            () => commit(types.CHECKOUT_SUCCESS), // 성공핸들러
            () => commit(types.CHECKOUT_FAIL, cartItems) // 실패핸들러
        )
    }
}

내부 사용

methods: {
    ...mapActions([
        'increment',
        'incrementBy',
    ]),
    ...mapActions({
        add: 'increment',
    }),
}

참고

[1] https://vuex.vuejs.org/kr/, 2021.11.10

반응형