Vuex

suyeon·2022년 2월 28일
0
  1. Vuex 사용 이유? 변수를 프로젝트 전체에서 사용 가능하도록 한다.

  2. 처리 흐름?
    dispatch -> Actions(commit) -> Mutations -> state -> Getters
    (이때, dispatch~Mutations는 데이터 반영, state~Getters는 데이터 조회 단계이다.)

  3. 사용 방법?

yarn add vuex@next // vue3에서는 vuex@next를 사용한다.

components>Notes

<template>
  <ul>
    <li v-for="(note, index) in notes" :key="index">{{note}}</li>
  </ul>
  <input type="text" v-model="title" @keypress.enter="save">
<!--  we want to push this input value into note array, so @key..-->
<!-- save는 함수다.-->
</template>

<script>
import {ref} from 'vue';
export default {
  name: 'NotesComponent',
  setup() {
    const notes = ref([]);
    const title = ref("");
    function save() {
      notes.value.push(title.value);
      title.value="";
    }
    return {
      notes,
      title,
      save,
    }
  }
}
</script>

router>index.js

import {createStore} from 'vuex';

const store = createStore({
    state:{
        title: "Vuex Store"
    },
    getters:{},
    mutations:{},
    actions:{},
});

export default store;

main.js

import { createApp } from 'vue';
import App from './App.vue';
import store from './store';

createApp(App).use(store).mount('#app')

App.vue

<template>
  <h1>Vuex turitorial</h1>
  {{ $store.state.title }} // 보여주기
  <Notes></Notes>
  <router-view></router-view>
</template>

<script>
import Notes from './components/Notes'

export default {
  components: {Notes,},
  setup() {
    return {};
  },
};
</script>

창을 띄워보면, store>index.js의 title이 화면에 찍히는 것을 확인할 수 있다.


Notes.vue
Notes.vue 컴포넌트에 import {useStore} from "vuex";를 하고,
import {computed} from 'vue'; 를 해준다.

setup() 안에 const store = useStore();를 해주고,
const notes = computed(() => store.state.notes)로 변경해준다.

변경된 Notes.vue 코드는 아래와 같다.

<template>
  <ul>
    <li v-for="(note, index) in notes" :key="index">{{note}}</li>
  </ul>
  <input type="text" v-model="title" @keypress.enter="save">
<!--  we want to push this input value into note array, so @key..-->
<!-- save는 함수다.-->
</template>

<script>
import {useStore} from "vuex";
import {computed, ref} from 'vue';

export default {
  name: 'NotesComponent',
  setup() {
    const store = useStore();
    const notes = computed(() => store.state.notes)
    const title = ref("");
    function save() {
      notes.value.push(title.value);
      title.value="";
    }
    return {
      notes,
      title,
      save,
    }
  }
}
</script>

store>index.js
index.js도 변경해줘야 한다.
state: {} 부분에 notes: [] 코드를 추가해준다.
전체 코드는 아래와 같다.

import {createStore} from 'vuex';

const store = createStore({
    state:{
        title: "Vuex Store",
        notes: [],
    },
    getters:{},
    mutations:{},
    actions:{},
});

export default store;

이제 받은 input 값인 title을 notes에 추가해주기로 한다. 이때 notes는 변경될 것이기 때문에 mutations를 이용한다.
그래서, Notes.vue 컴포넌트의 function을 아래와 같이 바꿔준다.

    function save() {
      store.commit('SAVE_NOTE', title.value);
      title.value="";
    }

Notes.vue의 전체 코드는 아래와 같다.

<template>
  <ul>
    <li v-for="(note, index) in notes" :key="index">{{note}}</li>
  </ul>
  <input type="text" v-model="title" @keypress.enter="save">
<!--  we want to push this input value into note array, so @key..-->
<!-- save는 함수다.-->
</template>

<script>
import {useStore} from "vuex";
import {computed, ref} from 'vue';

export default {
  name: 'NotesComponent',
  setup() {
    const store = useStore();
    const notes = computed(() => store.state.notes)
    const title = ref("");
    function save() {
      store.commit('SAVE_NOTE', title.value);
      title.value="";
    }
    return {
      notes,
      title,
      save,
    }
  }
}
</script>

물론, store>index.js도 변경해줘야 한다. mutations 부분이 수정되었다.

import {createStore} from 'vuex';

const store = createStore({
    state:{
        title: "Vuex Store",
        notes: [],
    },
    getters:{},
    mutations:{
        SAVE_NOTE(state, title) {
            state.notes.push(title)
        }
    },
    actions:{},
});

export default store;

여기까지 이해가 되었다면, 아래와 같이 한번 더 수정을 해준다. save 함수와 actions 부분이 변경된 것을 확인할 수 있다.

Notes.vue

<template>
  <ul>
    <li v-for="(note, index) in notes" :key="index">{{note}}</li>
  </ul>
  <input type="text" v-model="title" @keypress.enter="save">
<!--  we want to push this input value into note array, so @key..-->
<!-- save는 함수다.-->
</template>

<script>
import {useStore} from "vuex";
import {computed, ref} from 'vue';

export default {
  name: 'NotesComponent',
  setup() {
    const store = useStore();
    const notes = computed(() => store.state.notes)
    const title = ref("");
    function save() {
      store.dispatch('saveNote', title.value);
      title.value="";
    }
    return {
      notes,
      title,
      save,
    }
  }
}
</script>

index.vue

import {createStore} from 'vuex';

const store = createStore({
    state:{
        title: "Vuex Store",
        notes: [],
    },
    getters:{},
    mutations:{
        SAVE_NOTE(state, title) {
            state.notes.push(title)
        }
    },
    actions:{
        saveNote({commit}, title) {
            commit('SAVE_NOTE', title)
        }
    },
});

export default store;

store>index.js

이번에는 getters를 사용해보겠다.
store>index.js에서 getters 부분이 수정되었다. totalNote를 계산해보기 위해 computed를 사용했다.

import {createStore} from 'vuex';

const store = createStore({
    state:{
        title: "Vuex Store",
        notes: [],
    },
    getters:{
        totalNotes(state) {
            return state.notes.length
        }
    },
    mutations:{
        SAVE_NOTE(state, title) {
            state.notes.push(title)
        }
    },
    actions:{
        saveNote({commit}, title) {
            commit('SAVE_NOTE', title)
        }
    },
});

export default store;

Notes.vue
Notes.vue setup(){} 안에
const totalNotes = computed(() => store.getters.totalNotes)
코드를 추가해준 후,
template 태그에서

Total Notes : {{totalNotes}}

를 보여준다.

<template>
  <ul>
    <li v-for="(note, index) in notes" :key="index">{{note}}</li>
  </ul>
  <input type="text" v-model="title" @keypress.enter="save">
<!--  we want to push this input value into note array, so @key..-->
<!-- save는 함수다.-->
  <p>Total Notes : {{totalNotes}}</p>
</template>

<script>
import {useStore} from "vuex";
import {computed, ref} from 'vue';

export default {
  name: 'NotesComponent',
  setup() {
    const store = useStore();
    const notes = computed(() => store.state.notes)
    const totalNotes = computed(() => store.getters.totalNotes)

    const title = ref("");
    function save() {
      store.dispatch('saveNote', title.value);
      title.value="";
    }
    return {
      notes,
      title,
      save,
      totalNotes,
    }
  }
}
</script>

마지막으로 component를 나눠봤다.

components 폴더에 AddNewNote.vue를 생성하고, 코드를 분리했다.

AddNewNote.vue

<template>
  <div>
    <input type="text" v-model="title" @keypress.enter="save">
    <!--  we want to push this input value into note array, so @key..-->
    <!-- save는 함수다.-->
    <p>Total Notes : {{totalNotes}}</p>
  </div>
</template>

<script>
import {useStore} from "vuex";
import {computed, ref} from 'vue';

export default {
  name: 'NotesComponent',
  setup() {
    const store = useStore();
    const totalNotes = computed(() => store.getters.totalNotes)

    const title = ref("");
    function save() {
      store.dispatch('saveNote', title.value);
      title.value="";
    }
    return {
      title,
      save,
      totalNotes,
    }
  }
}
</script>

Notes.vue

<template>
  <AddNewNote></AddNewNote>
  <ul>
    <li v-for="(note, index) in notes" :key="index">{{note}}</li>
  </ul>
</template>

<script>
import AddNewNote from "@/components/AddNewNote";
import {useStore} from "vuex";
import {computed,} from 'vue';

export default {
  name: 'NotesComponent',
  components: {AddNewNote},
  setup() {
    const store = useStore();
    const notes = computed(() => store.state.notes)

    return {
      notes,
    }
  }
}
</script>

store>index.js

import {createStore} from 'vuex';

const store = createStore({
    state:{
        title: "Vuex Store",
        notes: [],
    },
    getters:{
        totalNotes(state) {
            return state.notes.length
        }
    },
    mutations:{
        SAVE_NOTE(state, title) {
            state.notes.push(title)
        }
    },
    actions:{
        saveNote({commit}, title) {
            commit('SAVE_NOTE', title)
        }
    },
});

export default store;

0개의 댓글