Meme's IT

[Vue] TodoList 만들어보기 본문

FrontEnd/Vue

[Vue] TodoList 만들어보기

Memez 2023. 11. 2. 17:59

 

Vue를 이용해서 TodoList를 만들어보자

완성 이미지

 

 


 

0. 사전준비

작성하기 편하게 html과 js을 분리해준다.

html에는 기본적인 형식과 vue의 cnd을 넣어주고,

js에는 기본적인 틀을 만들어준다.

<div id="app">
    <!-- 여기에 코드 작성 -->
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="./js파일.js"></script>
const { createApp,ref } = Vue

const app = createApp({
    setup() {

        return {

        }
    }
})
app.mount('#app')

 

 

1. Todo 항목 추가하기

해야하는 일을 담을 todos라는 배열과

새롭게 추가할 newTodo라는 항목을 만들어준다.

그리고 newTodo를 todos에 추가해줄 addTodo 함수도 정의해준다. (return에 추가하는건 생략)

const todos = ref([])
const newTodo = ref('')
const addTodo = function () {
    todos.value.push(newTodo.value)
    newTodo.value = ''
}
  • push로 받아온 newTodo를 todos에 넣고 초기화 해줘야한다.
  • v-model로 input에 입력한 데이터를 newTodo에 받아온다.
  • keyup.enter과 click으로 추가될 수 있도록 v-on을 이용한다. 
<h1>Todo List</h1>
<input type="text" v-model="newTodo" @keyup.enter="addTodo">
<button @click="addTodo">ADD</button>
<p>{{todos}}</p>

입력한 후, 엔터나 ADD를 누르면 새로운 항목이 들어가는 것을 확인할 수 있다.

 

 

2. Todos에 있는 항목들 출력하기

v-for을 이용해서 출력할 수 있다!

우선 위의 입력창과 구문하기 위해 입력창은 div로 빼주고,,

리스트로 출력하므로 ul,li를 이용

v-for은 다음과 같이 사용한다

<ul>
    <li v-for="todo in todos">
        <p>{{todo}}</p>
    </li>
</ul>

그럼 이런 결과가 나오는데..

너무 못생겼으니까 스타일을 조금만 주자

<ul style="padding: 0px;">
    <li v-for="todo in todos" style="list-style-type: none;">
        <input type="checkbox">
        {{todo}}
    </li>
</ul>

 

3. 리스트에서 완료한 항목은 줄 그어주기

todos에서 항목의 각각의 값이 내가 완료인지 아닌지를 가져야하므로,

js에서 addtodo함수를 살짝 수정해준다.

const addTodo = function () {
    const tmp = {
        text: newTodo.value,
        completed: false,
    }
    todos.value.push(tmp)
    newTodo.value = ''
}

todos에 넣을 때, 값만 넣는 것이 아니라 값+완료했는지를 같이 넣어준다

html도 수정해준다.

  • style에 완료일 때의 스타일을 클래스로 만들어주고
  • v-bind를 이용해서 todo.completed가 true라면 클래스를 추가해준다.
  • 체크박스를 클릭하면 todo의 completed가 변해야 하므로 v-model을 이용해준다
<li v-for="todo in todos" :class="{'iscomplete':todo.completed}" style="list-style-type: none;"> 
    <input type="checkbox" v-model="todo.completed">
    {{todo.text}}
</li>

 

이제 완료하면 이렇게 체크가 된다

 

 

4. 항목 삭제 버튼 만들기

우선, 삭제하려면 어떤 항목을 삭제할 것인지를 알려줘야하는데 그런 값이 없다

→ 처음에 넣을 때 키값을 넣어주자 +  인덱스도 같이 넣어주자

공식문서에서 key와 인덱스를 지정하는 방법이 있음

 

+ 버튼에는 지우는거 넣어주기

<li v-for="(todo, index) in todos" :key="todo.id" :class="{'iscomplete':todo.completed}"> 
    <input type="checkbox" v-model="todo.completed">
    {{todo.text}}
    <button @click="deleteTodo(index)">DELETE</button>
</li>

 

js파일에서 deleteTodo 함수 만들어주기

const deleteTodo = function (index) {
    todos.value.splice(index, 1)
}

splice(index, 1) = index순서부터 1개 자르기

 

filter을 이용해서 하는건 html에서 deleteTodo(todo.id)로 해주고

const deleteTodo = function (id) {
    todos.value = todos.value.filter((todo) => todo.id != id)
}

이렇게 해도 된다.

 

 

5. 완료 항목 전체 삭제 만들기

완료항목을 다 지우기 위해 deleteCompletedTodos함수를 만들어 준다.

const deleteCompletedTodos = function () {
    // todo.completed가 true인 애들만 삭제
    todos.value = todos.value.filter((todo) => {
        return !todo.completed
    })
}
<button @click="deleteCompletedTodos">완료 항목 삭제</button>

버튼도 만들어준다.

 

 

근데, 굳이 완료된 애들도 없는데 완료항목 삭제 버튼이 있어야할까?

6. 완료된거 없을 땐 안보이게 해주기

완료된 항목이 있나 체크하는 함수를 만들어주기 = todoCount

 

⭐computed 이용

기존 변수를 수정하지 않고, 계산된 값만 가지고 새로운 변수를 만들고 싶을 때!

computed 메서드 내에서 사용하는 변수가 변경이 생기면 새로 계산함!

 

computed를 사용하기 위해 import해오고

const { createApp, ref, computed } = Vue
const todoCount = computed(() => {
    return todos.value.filter((todo) => todo.completed).length > 0
})

todo에서 completed가 true면 남겨주고, 그거의 길이가 0보다 크면, true가 되도록 리턴

그니까, todoCount가 true다? = 완료된게 하나라도 있다

 

그리고, 완료항목삭제 버튼에 v-if 추가해준다

<button v-if="todoCount" @click="deleteCompletedTodos">완료 항목 삭제</button>

 

 

※ 참고

v-if와 v-show의 차이

# v- if

v-if는 요소가 아예 안보임  -> 자주일어나는 일이거나, volume이 큰 요소라면 비효율적임
처음에 없다: 눈에 보이지 않아도 되는 상황이 많다면 유리
즉, 자주 변경되거나 보여야한다면 v-if는 비효율적이다

 

# v-show

v-show는 display: none이 되서 콘솔에서는 확인 가능

-> 자주 일어나지 않는다면 이게 오히려 비효율적임(굳이 필요없을때?)
우리 눈에 보이지 않지만, DOM에는 존재한다
즉, 안보이는 상황이 많다면 v-show가 비효율적이다.

 

 

그럼 꿋!

완료된게 없으면 안보이다가
체크되면 삭제버튼 on

'FrontEnd > Vue' 카테고리의 다른 글

[Vue] Conditional Rendering(v-if, v-show)  (0) 2023.11.06
[Vue] Computed 속성  (0) 2023.11.06
[Vue] Form Input Bindings  (0) 2023.11.02
[Vue] v-on  (0) 2023.11.02
[Vue] v-bind (Attribute, Class, Style)  (0) 2023.11.02