[Vue.js] TodoList 만들기(연습2-내용정리, component 적용, 초기화 기능 구현 등)
2021. 3. 10. 22:18ㆍVue.js
<App.vue>
<template>
<div class="container flex flex-col items-center bg-gray-200 m-auto p-5 rounded-3xl">
<h1 class="text-3xl p-2">Todo List</h1>
<input type="text" class="form-control border mb-2 rounded-md h-10 w-1/3" v-model="userInput" @keyup.enter="addNewTodo" placeholder=" 할 일 생성">
<div class="w-full text-center flex flex-col items-center">
<template v-for="todo in activeTodoList" v-bind:key="todo.label">
<!--아래처럼 한줄에 v-for를 담아도 되고 위처럼 template로 분리해서 담아도 됨-->
<!--<button class="bg-green-200 w-6/12 text-left px-3 py-3" v-for="todo in activeTodoList" v-bind:key="todo.label" @click="toggleTodoState(todo)">-->
<!--
<button class="bg-green-200 w-6/12 text-left p-3 border border-black" @click="toggleTodoState(todo)">
{{todo.label}}
</button>
Todo 컴포넌트 적용으로 위 내용 삭제 -->
<todo
:label="todo.label"
@componentClick="toggleTodoState(todo)"
/>
<!-- @componentClick="toggleTodoState(todo)"
컴포넌트 내부에서 발생시킨 componentClick 이벤트를 받아 toggleTodoState함수를 실행
-->
</template>
</div>
<div class="flex items-center mt-2 mb-2">
<button class="btn-primary m-1" @click="chageCurrentState('active')">할 일</button>
<button class="btn-secondary m-1" @click="chageCurrentState('done')">완료</button>
<button class="btn-success m-1" @click="chageCurrentState('all')">전체</button>
<button class="btn-danger m-1" @click="resetTodoList">초기화</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import Todo from './components/TodoVue.vue'
export default defineComponent({
name: 'App',
data(){
return{
userInput: "", //사용자 입력값을 받아올 변수 선언 //v-model로 연결
todoList: [] = [], //사용자 입력값을 보관할 배열 생성
currentState:'active' //출력할 상태값을 가진 변수 선언 //default값으로 'active'
};
},
/* computed 속성 */
//data 속성 값의 변화에 따라 자동으로 다시 연산
//ex) computed 속성에서 사용하고 있는 data 속성 값이 변경되면서 전체 값을 다시 계산함
/* computed 속성과 methods 속성의 차이점 */
//methods 속성은 호출할 때만 해당 로직이 수행
//computed 속성은 대상 data의 값이 변경되면 자동으로 수행
//즉, 수동적으로 data를 갱신시키느냐, 능동적으로 data를 갱신시키느냐 그 차이
computed:{
//v-for="todo in activeTodoList"
//computed안에 함수를 담으면 activeTodoList() 함수가 아닌 activeTodoList와 같이 변수처럼 사용 가능
//todoList 배열에 필터(filter)를 걸고
//currentState가 'all'이거나 currentState값과 같은 값인 todo만 배열에 담아 리턴하는 함수
activeTodoList(){
return this.todoList.filter((todo : any) => this.currentState === 'all' || todo.state === this.currentState);
}
},
methods: {
//@click="chageCurrentState('active')
//state값을 받아 상태값을 변경하는 함수
chageCurrentState(state:any){
this.currentState = state;
},
//@keyup.enter="addNewTodo"
//keyup 이벤트(키입력 이벤트)가 발생하고 입력값이 enter이면 addNewTodo()함수를 실행한다는 의미
addNewTodo(){
//this.todoList.push(this.userInput); (초기 ver, string형태) //아래처럼 json형태로 바꿔 state를 추가함
this.todoList.push({
label: this.userInput, //json형태 갖추기 위해 label: this.userInput로 변경
state: 'active' //상태값을 가질 state 값 선언
});
//todoList에 userInput값을 추가한 뒤 userInput값은 ''으로 초기화 시켜주는 것
this.userInput = '';
},
//@click="toggleTodoState(todo)
//버튼 클릭시 state값을 변경하는 함수
//todo 파라미터는 클릭한 항목을 받을 변수
toggleTodoState(todo:any){
todo.state = todo.state === 'active' ? 'done' : 'active';
},
//초기화
resetTodoList(){
this.todoList.length = 0;
}
},
components: {
Todo
}
})
</script>
<style lang="postcss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.btn-primary {
@apply py-1 px-3 bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 focus:ring-offset-blue-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-secondary {
@apply py-1 px-3 bg-gray-600 hover:bg-gray-700 focus:ring-gray-500 focus:ring-offset-gray-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-success {
@apply py-1 px-3 bg-green-600 hover:bg-green-700 focus:ring-green-500 focus:ring-offset-green-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-danger {
@apply py-1 px-3 bg-red-600 hover:bg-red-700 focus:ring-red-500 focus:ring-offset-red-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-warning {
@apply py-1 px-3 bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500 focus:ring-offset-yellow-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-info {
@apply py-1 px-3 bg-purple-600 hover:bg-purple-700 focus:ring-purple-500 focus:ring-offset-purple-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
</style>
<TodoVue.vue>
<template>
<button class="bg-white w-6/12 text-left p-2 mb-1 mt-1 rounded-md hover:bg-green-200" @click="clickButton">
{{ label }}
</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
props:{
label:{
type: String,
required: true
}
},
//해당 컴포넌트에서 발생하는 이벤트를 외부에 알려줘야 함
//@click="clickButton" //버튼 클릭시 clickButton() 함수 실행
methods:{
clickButton(){
this.$emit('componentClick');
}
},
name: 'Todo'
});
</script>
'Vue.js' 카테고리의 다른 글
[Vue 3.0 기초] 1강: 워밍업 (0) | 2021.03.23 |
---|---|
[Vue.js] Vue 초기 프로젝트 생성 관련 명령어(feat.vite) (0) | 2021.03.11 |
[Vue.js] VITE 개념(feat.CLI) (0) | 2021.03.10 |
[Vue.js] TodoList 만들기(연습) (0) | 2021.03.09 |
[Vue.js] npm, package.json 개념 (0) | 2021.02.20 |