Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- mybatis
- Eclipse
- Git
- oracle
- aws
- 자바
- 코틀린
- JPA
- Security
- jquery
- db
- Spring
- 함수
- 오라클
- IntelliJ
- GitHub
- 프로그래머스
- kotlin
- 넥사크로
- Vue
- 쿼리
- JavaScript
- 알고리즘
- error
- 스프링
- Java
- 방법
- 시큐리티
- 에러
- 생성
Archives
- Today
- Total
송민준의 개발노트
Vuex 사용 본문
npm i vuex
상태
1. 단일 상태 트리
- vuex는 단일 상태 트리를 사용함. 이 단일 객체는 모든 어플리케이션 수준의 상태를 포함하며 "원본 소스"역할을 함. 이는 각 어플리케이션마다 하나의 저장소만 갖게 된다는 것을 의미.
- 아래는 mapState 헬퍼를 이용해서 관리
isAddBoard라는 모달상태값을 vuex의 저장소를 이용해서 관리
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
isAddBoard: false
}
})
export default store
main.js
import Vue from 'vue'
import router from './router'
import App from './App.vue'
import store from './store'
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
<template>
<AddBoard v-if="isAddBoard" @close="isAddBoard=false" @submit="onAddBoard"></AddBoard>
</template>
<script>
import AddBoard from './AddBoard.vue'
import {mapState} from 'vuex'
export default {
components: {
AddBoard
},
computed: {
...mapState([
'isAddBoard'
]),
// foo() {
//
// }
},
methods: {
addBoard() {
this.isAddBoard = true
}
}
}
변이(mutation)
vuex 저장소에서 실제 상태를 변경하는 방법은 변이하는 것임. 이벤트와 매우 유사함.
동기적인 작업.
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
isAddBoard: false
},
mutations: {
SET_IS_ADD_BOARD (state, toggle) {
state.isAddBoard = toggle
}
}
})
export default store
<template>
<div>
<div class="home-title">Personal Boards</div>
<div class="board-list" ref="boardList">
<div class="board-item" v-for="b in boards" :key="b.id"
:data-bgcolor="b.bgColor" ref="boardItem">
<router-link :to="`/b/${b.id}`">
<div class="board-item-title">{{b.title}}</div>
</router-link>
</div>
<div class="board-item board-item-new">
<a class="new-board-btn" href="" @click.prevent="SET_IS_ADD_BOARD(true)">
Create new board...
</a>
</div>
</div>
<AddBoard v-if="isAddBoard" @close="isAddBoard=false" @submit="onAddBoard"></AddBoard>
</div>
</template>
<script>
import {board} from '../api'
import AddBoard from './AddBoard.vue'
import {mapState, mapMutations} from 'vuex'
export default {
components: {
AddBoard
},
data() {
return {
loading: false,
boards: [],
error: ''
}
},
computed: {
...mapState([
'isAddBoard'
]),
// foo() {
//
// }
},
created() {
this.fetchData()
},
/**
* -------- updated ----------
* 가상 DOM을 렌더링 하고 실제 DOM이 변경된 이후 호출됨.
* 만약 변경된 값들을 DOM을 이용해 접근하고 싶다면, updated 훅이 적절
* 여기서 data를 변경하는 것은 무한 루프를 일으킬 수 있음(주의)
*/
updated() {
// 컴포넌트의 reference 중에 boardItem을 찾아옴
this.$refs.boardItem.forEach(el => {
el.style.backgroundColor = el.dataset.bgcolor
})
},
methods: {
...mapMutations([
'SET_IS_ADD_BOARD'
]),
fetchData() {
this.loading = true
board.fetch()
.then(data => {
this.boards = data.list
})
.finally(()=> {
this.loading = false
})
},
// 방법 1 - commit을 이용해서 상태 변경
// addBoard() {
// // this.isAddBoard = true
// this.$store.commit('SET_IS_ADD_BOARD', true)
// },
onAddBoard(title) {
board.create({title})
.then(() => this.fetchData())
}
}
}
</script>
<style scoped>
.home-title {
padding: 10px;
font-size: 18px;
font-weight: bold;
}
.board-list {
padding: 10px;
display: flex;
flex-wrap: wrap;
}
.board-item {
width: 23%;
height: 100px;
margin: 0 2% 20px 0;
border-radius: 3px;
}
.board-item-new {
background-color: #ddd;
}
.board-item a {
text-decoration: none;
display: block;
width: 100%;
height: 100%;
}
.board-item a:hover,
.board-item a:focus {
background-color: rgba(0,0,0, .1);
color: #666;
}
.board-item-title {
color: #fff;
font-size: 18px;
font-weight: 700;
padding: 10px;
}
.board-item a.new-board-btn {
display: table-cell;
vertical-align: middle;
text-align: center;
height: 100px;
width: inherit;
color: #888;
font-weight: 700;
}
</style>
<template>
<Modal>
<div slot="header">
<h2>
Create new board
<a href="" class="modal-default-button"
@click.prevent="SET_IS_ADD_BOARD(false)">×</a>
</h2>
</div>
<div slot="body">
<form id="add-board-form"
@submit.prevent="addBoard">
<input class="form-control" type="text" v-model="input" ref="input">
</form>
</div>
<div slot="footer">
<button class="btn" :class="{'btn-success': valid}" type="submit"
form="add-board-form" :disabled="!valid">
Create Board</button>
</div>
</Modal>
</template>
<script>
import Modal from './Modal.vue'
import {mapMutations} from 'vuex'
export default {
components: {
Modal
},
data() {
return {
input: '',
valid: false
}
},
watch: {
input(v) {
this.valid = v.trim().length > 0
}
},
mounted() {
this.$refs.input.focus()
},
methods: {
...mapMutations([
'SET_IS_ADD_BOARD'
]),
// close() {
// this.$emit('close')
// },
addBoard() {
// this.$emit('close')
this.SET_IS_ADD_BOARD(false)
this.$emit('submit', this.input)
}
}
}
</script>
<style scoped>
</style>
액션
액션은 변이와 유사함.
상태를 변이시키는 대신 액션으로 변이에 대한 커밋을 함.
작업에는 임의의 비동기 작업이 포함될 수 있음.
<template>
<Modal>
<div slot="header">
<h2>
Create new board
<a href="" class="modal-default-button"
@click.prevent="SET_IS_ADD_BOARD(false)">×</a>
</h2>
</div>
<div slot="body">
<form id="add-board-form"
@submit.prevent="addBoard">
<input class="form-control" type="text" v-model="input" ref="input">
</form>
</div>
<div slot="footer">
<button class="btn" :class="{'btn-success': valid}" type="submit"
form="add-board-form" :disabled="!valid">
Create Board</button>
</div>
</Modal>
</template>
<script>
import Modal from './Modal.vue'
import {mapMutations, mapActions} from 'vuex'
export default {
components: {
Modal
},
data() {
return {
input: '',
valid: false
}
},
watch: {
input(v) {
this.valid = v.trim().length > 0
}
},
mounted() {
this.$refs.input.focus()
},
methods: {
...mapMutations([
'SET_IS_ADD_BOARD'
]),
...mapActions([
'ADD_BOARD'
]),
// close() {
// this.$emit('close')
// },
addBoard() {
// this.$emit('close')
this.SET_IS_ADD_BOARD(false)
this.$emit('submit')
this.ADD_BOARD({title: this.input})
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<div class="home-title">Personal Boards</div>
<div class="board-list" ref="boardList">
<div class="board-item" v-for="b in boards" :key="b.id"
:data-bgcolor="b.bgColor" ref="boardItem">
<router-link :to="`/b/${b.id}`">
<div class="board-item-title">{{b.title}}</div>
</router-link>
</div>
<div class="board-item board-item-new">
<a class="new-board-btn" href="" @click.prevent="SET_IS_ADD_BOARD(true)">
Create new board...
</a>
</div>
</div>
<AddBoard v-if="isAddBoard" @close="isAddBoard=false" @submit="onAddBoard"></AddBoard>
</div>
</template>
<script>
import {board} from '../api'
import AddBoard from './AddBoard.vue'
import {mapState, mapMutations} from 'vuex'
export default {
components: {
AddBoard
},
data() {
return {
loading: false,
boards: [],
error: ''
}
},
computed: {
...mapState([
'isAddBoard'
]),
// foo() {
//
// }
},
created() {
this.fetchData()
},
/**
* -------- updated ----------
* 가상 DOM을 렌더링 하고 실제 DOM이 변경된 이후 호출됨.
* 만약 변경된 값들을 DOM을 이용해 접근하고 싶다면, updated 훅이 적절
* 여기서 data를 변경하는 것은 무한 루프를 일으킬 수 있음(주의)
*/
updated() {
// 컴포넌트의 reference 중에 boardItem을 찾아옴
this.$refs.boardItem.forEach(el => {
el.style.backgroundColor = el.dataset.bgcolor
})
},
methods: {
...mapMutations([
'SET_IS_ADD_BOARD'
]),
fetchData() {
this.loading = true
board.fetch()
.then(data => {
this.boards = data.list
})
.finally(()=> {
this.loading = false
})
},
// 방법 1 - commit을 이용해서 상태 변경
// addBoard() {
// // this.isAddBoard = true
// this.$store.commit('SET_IS_ADD_BOARD', true)
// },
onAddBoard() {
this.fetchData()
}
}
}
</script>
<style scoped>
.home-title {
padding: 10px;
font-size: 18px;
font-weight: bold;
}
.board-list {
padding: 10px;
display: flex;
flex-wrap: wrap;
}
.board-item {
width: 23%;
height: 100px;
margin: 0 2% 20px 0;
border-radius: 3px;
}
.board-item-new {
background-color: #ddd;
}
.board-item a {
text-decoration: none;
display: block;
width: 100%;
height: 100%;
}
.board-item a:hover,
.board-item a:focus {
background-color: rgba(0,0,0, .1);
color: #666;
}
.board-item-title {
color: #fff;
font-size: 18px;
font-weight: 700;
padding: 10px;
}
.board-item a.new-board-btn {
display: table-cell;
vertical-align: middle;
text-align: center;
height: 100px;
width: inherit;
color: #888;
font-weight: 700;
}
</style>
import Vue from 'vue'
import Vuex from 'vuex'
import * as api from '../api'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
isAddBoard: false
},
mutations: {
SET_IS_ADD_BOARD (state, toggle) {
state.isAddBoard = toggle
}
},
actions: {
ADD_BOARD(_, {title}) {
return api.board.create(title)
}
}
})
export default store
'웹 > Vue' 카테고리의 다른 글
Vue Lazy Loading (2) | 2021.07.20 |
---|---|
Vue - EventBus 정리 (0) | 2021.07.15 |
axios 사용 (0) | 2021.03.21 |
Vue 토이프로젝트 github에 올리기(Atom, git bash 사용) (0) | 2020.02.14 |
vue local storage에 값 넣기(로컬 스토리지) (0) | 2020.02.14 |