새로운 강의는 이제 https://memi.dev 에서 진행합니다.
memi가 Vue & Firebase로 직접 만든 새로운 사이트를 소개합니다.
모던웹(NEMV) 혼자 제작 하기 3기 - 49 뷰저장소(vuex) 이정도만 쓰자
토큰 유무에 따라 로그인/아웃 상태를 전체 페이지에서 판단할 수 있는 뷰저장소에 대해 알아봅니다.
복잡해보이는 뷰저장소 기능 중 딱 한 기능만 배우고 그것만 써보겠습니다.
토큰 존재 유무로 페이지 바꿔보기
우측 상단 메뉴에 로그인은 토큰이 있을 때는 안보여야겠죠?
<v-list-tile v-if="localStorage.getItem('token')" @click="$router.push('/sign')">
<v-list-tile-title>로그인</v-list-tile-title>
</v-list-tile>
<v-list-tile v-else @click="signOut">
<v-list-tile-title>로그아웃</v-list-tile-title>
</v-list-tile>
이렇게 하면 될 것 같은데 안됩니다.
로컬스토리지는 뷰의 것이 아니기 때문에 에러가 납니다.
전역변수를 써도 마찬가지입니다.
sign.vue와 App.vue등 서로 다른 콤포넌트가 자원을 공유해서 변수를 사용하고 그 변수가 변경될 때 일반적인 바인딩 효과가 일어나지 않는 것입니다.
eg)sign.vue에서 변경한 변수를 App.vue DOM이 알아차리지 못하는 것 같습니다.
뷰저장소(vuex)
뷰 저장소에 대해 간단히 알아봅니다.
참고: https://vuex.vuejs.org/kr/
5가지가 있는데 쉽게 풀어보면
- 상태: 전역 변수
- Getter: 변수 조합용
- 변이: 변수 변경
- 액션: 비동기 변수 변경
- 모듈: 여러개 사용할 때
더 깊은 뜻이 있지만 간단하게 풀어 본 것입니다.
이중 상태와 변이만 이용해서 전역변수를 사용해보겠습니다.
저장소 정의 하기
뷰컴3(vue-cli)로 프로젝트를 만들 때 vuex를 선택했기 때문에 fe/src/store.js가 골격이 만들어져 있습니다.
fe/src/store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: localStorage.getItem('token')
},
mutations: {
getToken (state) {
state.token = localStorage.getItem('token')
},
delToken (state) {
localStorage.removeItem('token')
state.token = null
}
},
actions: {
}
})
- state에 전역으로 사용할 변수를 선언합니다. 초기값을 로컬스토리지값을 넣습니다.(새로고침해도 토큰값을 유지하기 위함)
- mutations에 전역변수가 변이할 때 할 일들을 정의 해둡니다.
저장소 사용하기
읽을때
<template>
<div>{{$store.state.token}}</div>
</template>
<script>
export default {
mounted () {
console.log(this.$store.state.token)
}
}
</script>
쓸 때
export default {
mounted () {
this.$store.commit('getToken')
this.$store.commit('delToken')
// this.$store.commit('getToken', localStorage.getItem('token'))
}
}
함수 명과 값을 넘겨 줄 수 있습니다.
위에 주석처리 해놓은 것처럼 값을 넘겨 사용할 수 있지만,
관리적인 측면에서 getToken은 공용으로 사용하기 때문에 매번 저렇게 쓰는 것 보다 변이 안에 넣는게 좋겠죠?
화면에 반영하기
메인 화면
fe/src/App.vue
<template>
<v-app>
<v-navigation-drawer
persistent
v-model="drawer"
enable-resize-watcher
fixed
app
>
<v-list>
<v-list-tile
value="true"
v-for="(item, i) in items"
:key="i"
:to="item.to"
>
<v-list-tile-action>
<v-icon v-html="item.icon"></v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title v-text="item.title"></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-toolbar
app
>
<v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
<v-toolbar-title v-text="title"></v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-menu bottom left>
<v-btn icon slot="activator">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-tile v-if="!$store.state.token" @click="$router.push('sign')">
<v-list-tile-title>로그인</v-list-tile-title>
</v-list-tile>
<v-list-tile v-else @click="signOut">
<v-list-tile-title>로그아웃</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-toolbar-items>
</v-toolbar>
<v-content>
<router-view/>
</v-content>
<v-footer fixed app>
<span>© 2017 {{$store.state.token}}</span>
</v-footer>
</v-app>
</template>
<script>
export default {
name: 'App',
data () {
return {
drawer: null,
items: [
{
icon: 'home',
title: '홈aaa',
to: {
path: '/'
}
},
{
icon: 'face',
title: '사용자관리',
to: {
path: '/user'
}
},
{
icon: 'face',
title: 'header',
to: {
path: '/header'
}
}
],
title: this.$apiRootPath
}
},
mounted () {
},
methods: {
signOut () {
// localStorage.removeItem('token')
this.$store.commit('delToken')
this.$router.push('/')
}
}
}
</script>
- v-if=”!$store.state.token” 으로 토큰이 없을때는 로그인 있을때는 로그아웃이 처리되었습니다.
- 로그아웃에 delToken 변이를 호출해서 토큰 값을 지우는 것이 확인되었습니다.
로그인 화면
fe/src/views/sign.vue
signIn () {
axios.post(`${this.$apiRootPath}sign/in`, this.form)
.then(r => {
if (!r.data.success) return console.error(r.data.msg)
localStorage.setItem('token', r.data.token)
this.$store.commit('getToken')
this.$router.push('/')
// location.href = '/header'
})
.catch(e => console.error(e.message))
}
- 토큰을 받고 로컬스토리지에 써놓은 다음에 변이 getToken을 이용해 state.token을 갱신했습니다.
마치며
뮤테이션과 액션에 공용으로 사용할 함수들을 등록해 놓고 여러 콤포넌트에서 사용하면 복잡한 프로젝트에서 빛이 날 것 같습니다.
제 강좌를 보고 입사한 새내기 박군에게 뷰저장소를 어제 처음 배워봤는데요..
이제는 제가 제자네요~
제가 엄청 잘해서 이 강좌를 하고 있는 것이 아닙니다.
자료 생성 및 복습 겸 하고 있는 것이 제일 큰 이유죠.
그리고 하수도 강좌가 가능하고 하수가 만든 강좌가 조금 더 이해가 쉽지 않을까 하는 생각이 있는 것이죠..
댓글남기기