반응형
<App.vue>
<template>
<div id="app">
<TodoHeader></TodoHeader>
<TodoInput></TodoInput>
<TodoList></TodoList>
<TodoFooter></TodoFooter>
</div>
</template>
<script>
import TodoHeader from './components/TodoHeader.vue'
import TodoInput from './components/TodoInput.vue'
import TodoList from './components/TodoList.vue'
import TodoFooter from './components/TodoFooter.vue'
export default {
components: {
// 컴포넌트 태그명 : 컴포넌트 내용
TodoHeader,
TodoInput,
TodoList,
TodoFooter
}
}
</script>
<style>
body{
text-align: center;
background-color: #f6f6f6;
font-family: Ubuntu, sans-serif;
font-weight: 500;
letter-spacing: -0.8px;
}
input{
border-style: groove;
width: 200px;
}
button{
border-style: groove;
}
.shadow{
box-shadow: 5px 10px 10px rgba(0, 0, 0, 0.03);
}
</style>
<store.js>
import Vue from 'vue'
import Vuex from 'vuex'
//use 는 vue의 플러그인, vue를 사용할때 전역으로 모든 영역에 특정 기능을 추가하고 싶을때 사용한다.
Vue.use(Vuex);
const storage = {
// 원격 API를 간편하게 호출할수 있도록 브라우저에서 제공하는 함수
fetch(){
const arr = [];
if (localStorage.length > 0) {
for (let i = 0; i < localStorage.length; i++) {
if (localStorage.key(i) !== 'loglevel:webpack-dev-server') {
arr.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
}
}
}
return arr;
},
}
export const store = new Vuex.Store({
state:{
todoItems : storage.fetch()
},
getters:{
storedTodoItems(state){
return state.todoItems
}
},
mutations:{
// 뮤테이션에서 state 접근하는 방법은 인자로 받고 접근
addOneItem(state, todoItem) {
var obj = { completed: false, item: todoItem };
localStorage.setItem(todoItem, JSON.stringify(obj));
state.todoItems.push(obj);
},
remobvOneItem(state, payload) {
localStorage.removeItem(payload.todoItem.item);
state.todoItems.splice(payload.index, 1); //idx 데이터 하나 삭제
},
toggleOneItem(state, payload) {
state.todoItems[payload.index].completed = !state.todoItems[payload.index].completed;
// 로컬 스토리지 데이터를 갱신
localStorage.removeItem(payload.todoItem.item); //아이템 지우기
localStorage.setItem(payload.todoItem.item, JSON.stringify(payload.todoItem)); //아이템 다시 세팅
},
clearAllItem(state) {
localStorage.clear();
state.todoItems = [];
},
}
});
<TodoInput.vue>
<template>
<div class="inputBox shadow">
<input type="text" v-model="newTodoTtem" v-on:keyup.enter="addTodo">
<span class="addContainer" v-on:click="addTodo">
<i class="fa-solid fa-plus" style="color:#fff;"></i>
</span>
<Modal v-if="showModal" @close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">경고!</h3>
<p slot="body">할 일을 입력하세요</p>
</Modal>
</div>
</template>
<script>
import Modal from './common/AlertModal.vue'
export default {
components : {
Modal
},
// data는 함수. 하나의 객체만을 반환
data(){
return {
newTodoTtem:"",
showModal: false
}
},
methods: {
addTodo(){
if (this.newTodoTtem !== '') { //값이 있을때
// this.$emit('addTodoItem', this.newTodoTtem);
const text = this.newTodoTtem.trim();
this.$store.commit('addOneItem', text);
this.cleaerInput();
}else{
this.showModal = !this.showModal;
}
},
cleaerInput(){
this.newTodoTtem='';
},
}
};
</script>
<style lang="scss" scoped>
input:focus{
outline: none;
}
.inputBox{
background: #fff;
height: 50px;
line-height: 50px;
border-radius: 5px;
}
.inputBox input{
border-style: none;
font-size: 0.9rem;
}
.addContainer{
float: right;
background: linear-gradient(to right, #6478FB, #8763FB);
display: block;
width: 3rem;
border-radius: 0 5px 5px 0;
}
.addBtn{
color: #fff;
vertical-align: middle;
}
</style>
<TodoList.vue>
<template>
<div>
<transition-group name="list" tag="ul">
<li v-for="(todoItem, index) in this.storedTodoItems" v-bind:key="todoItem.item" class="shadow">
<i class="checkBth fa-solid fa-check" v-bind:class="{ checkBtnCompleted: todoItem.completed }"
v-on:click="toggleComplete({todoItem, index})"></i>
<!-- 객체.속성값으로 접근 -->
<span v-bind:class="{ textCompleted: todoItem.completed }"> {{ todoItem.item }}</span>
<span class="removeBtn" v-on:click="removeTodo({todoItem, index})">
<i class="fa-solid fa-trash-can"></i>
</span>
</li>
</transition-group>
</div>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex';
export default {
methods: {
...mapMutations({
removeTodo: 'remobvOneItem',
toggleComplete: 'toggleOneItem'
})
// removeTodo(todoItem, index) {
// // this.$emit('removeItem', todoItem, index);
// this.$store.commit('remobvOneItem', {todoItem, index});
// },
// toggleComplete(todoItem, index) {
// // this.$emit('toggleItem', todoItem, index);
// this.$store.commit('toggleOneItem', { todoItem, index });
// }
},
computed:{
// todoItems(){
// return this.$store.getters.storedTodoItems;
// },
...mapGetters(['storedTodoItems']),
// ...mapGetters({
// todoItems: 'storedTodoItems'
// }),
}
};
</script>
<style lang="scss" scoped>
ul{
list-style-type: none;
padding-left: 0px;
margin-top: 0;
text-align: left;
}
li{
display: flex;
margin: 10px 0;
min-height: 50px;
height: 50px;
line-height: 50px;
padding: 0 0.9rem;
background: #fff;
border-radius: 5px;
}
.checkBth{
line-height: 45px;
color: #62acde;
margin-right: 5px;
}
.checkBtnCompleted{
color: #b3adad;
}
.textCompleted{
text-decoration: line-through;
color: #b3adad;
}
.removeBtn{
margin-left: auto;
color: #de4343;
}
// 리스트 아이템 트렌지션 효과
.list-enter-active,
.list-leave-active {
transition: all 1s;
}
.list-enter,
.list-leave-to {
/* .list-leave-active below version 2.1.8 */
opacity: 0;
transform: translateY(-30px);
}
</style>
<TodoFooter.vue>
<template>
<div class="clearALlContainer">
<span class="clearAllBtn" v-on:click="clearTodo">Clear All</span>
</div>
</template>
<script>
import { mapMutations } from 'vuex';
export default {
methods: {
...mapMutations({
clearTodo: 'clearAllItem'
}),
// clearTodo() {
// // this.$emit('cleartAll');
// this.$store.commit('clearAllItem')
// }
}
};
</script>
<style lang="scss" scoped>
.clearALlContainer{
width: 8.5rem;
height: 50px;
line-height: 50px;
background-color: #fff;
border-radius: 5px;
margin: 0 auto;
}
.clearAllBtn{
color: #e20303;
display: block;
}
</style>
반응형
'vue.js > vue.js 2' 카테고리의 다른 글
49. <vue-todo> 프로젝트 구조화 (0) | 2022.08.02 |
---|---|
48. 프로젝트 구조화와 모듈화 방법 1, 2 (0) | 2022.08.02 |
46. 헬퍼 함수가 주는 간편함 (0) | 2022.08.02 |
45. mapState, mapGetters, mapMutations, mapActions | 헬퍼의 유연한 문법 (0) | 2022.08.02 |
44. Helper (각 속성들을 더 쉽게 사용하는 방법) (0) | 2022.08.02 |