본문 바로가기
Programming/Vue

[실습] 뷰(Vue)로 투두 리스트(Todo list) 구현하기 - UI, 레이아웃(Layout) 구성/구현하기

by 돌방로그 2022. 12. 21.

제목의 글을 설명하기에 앞서 정보전달의 목적도 있지만, 

제가 잊지않기 위해서 공부 및 정리하며 쓰는 글이라는 사실을 미리 고지합니다.

 

혹시라도 오입력된 정보가 있다면, 댓글 남겨주세요!


오늘의 Vue.js 실습 목표는 "투두 리스트 (Todo list) 만들어보기!" 입니다.

본 게시글에서 다루는 사항은 투두리스트(Todo List) Layout을 구현하는 과정입니다.

 


투두 리스트 레이아웃(Todo List Layout) 구현하기

사전 준비

아래 사항에 대해서 사전 준비가 완료되지 않으신 분들은 아래 링크를 참조하여 사전 준비를 진행합니다.

  1. Vue 프로젝트 생성 (참고: https://logs-jejustone.tistory.com/5)

 

혹시라도 아래 개념이 잘 기억나지 않으시는 분들은 관련 링크를 참조하시기 바랍니다.

 

파일 구조

Todo List의 기본적인 레이아웃을 구현하기 위해서 작업해야할 파일은 총 5개입니다.

각 vue 파일은 views와 components 하위에 위치하고 있습니다. 

저의 경우 최상위 컴포넌트인 PracticeTodo.vue 파일을 추후 웹 애플리케이션 레이아웃의 라우팅 기능을 적용하기 위해 views 폴더 하위에 위치시켜두었습니다.

 

각 파일은 하나의 컴포넌트이며, 컴포넌트의 상/하위 구조는 아래와 같습니다.

작업할 파일에 대한 간략한 설명은 아래를 참고하시면 됩니다.

  • PracticeTodo.vue
    • 목적: Todo List의 최상위 컴포넌트 파일로 하위 컴포넌트를 관리하고 Todo List의 실질적인 데이터 및 이벤트 처리를 하는 파일 
    • 경로: src\views\Practice
  • TodoHeader.vue
    • 목적: Todo List의 레이아웃에서 최상위에 위치하는 Header 파일로 Todo List의 타이틀을 표시하는 영역
    • 경로: src\components\Practice\Todo
  • TodoInput.vue
    • 목적: Todo List의 레이아웃에서 Header 하위에 위치하는 Input 파일로 Todo Item을 입력 및 추가하는 기능을 제공하는 영역
    • 경로: src\components\Practice\Todo
  • TodoList.vue
    • 목적: Todo List의 레이아웃에서 Footer 상위에 위치하는 List 파일로 등록된 Todo Item에 대해서 보여주고 개별적으로 Done, Delete 기능을 제공하는 영역
    • 경로: src\components\Practice\Todo
  • TodoFooter.vue
    • 목적: Todo List의 레이아웃에서 최하위에 위치하는 Footer 파일로 등록된 Todo Item의 수를 표시하거나 전체 삭제하는 기능을 제공하는 영역
    • 경로: src\components\Practice\Todo

 

 

결과 이미지

구현하기에 앞서 본 글을 따라하시면 아래와 같이 투두 리스트의 레이아웃이 구성되는 것을 확인하실 수 있습니다.

 

 

Layout 구조

TodoList는 크게 4가지 영역으로 구분하여 Layout이 구성되어 있습니다. 

  1. TodoHeader: TodoList의 Header 영역으로 타이틀을 표시하는 영역
  2. TodoFooter: TodoList의 Footer 영역으로 TodoList에 등록된 항목을 전체 삭제하는 기능이 제공되는 영역
  3. TodoInput: TodoList에 Todo Item을 입력하는 항목이 있는 영역 
  4. TodoList: TodoList에 등록된 Todo Item이 표시되는 영역

 

소스 코드

src\components\Practice\Todo\TodoHeader.vue

위 Layout 구조에서 TodoHeader 컴포넌트를 정의하는 파일을 구현합니다.

결과 이미지에서 보여지는 바와 같이 TodoHeader에는 'Todo'라는 타이틀만 표시하면 됩니다.

<!-- TodoHeader.vue -->

<template>
    <div id="todoHeader"> 
        <h2> Todo </h2>
    </div>
</template>

<script>
export default {};
</script>

<style scoped>
#todoHeader h2 {
    text-align: center;
}
</style>

<template>

  • Header 영역을 지정하기 위해 <div> 태그 사용 및 id 정의
  • 타이틀로 'Todo'가 표시되도록 <h2> 태그로 선언 

<style>

  • 타이틀을 선언하기 위해 사용한 <h2> 태그에 텍스트가 가운데 정렬되도록 'text-align' 속성 부여

 

src\components\Practice\Todo\TodoFooter.vue

위 Layout 구조에서 TodoFooter 컴포넌트를 정의하는 파일을 구현합니다.

결과 이미지에서 보여지는 바와 같이 TodoFooter에는 'Delete All' 버튼만 존재합니다.

<!-- TodoFooter.vue -->

<template>
    <div id="todoFooter">
        <button>Delete All</button>
    </div>
</template>

<script>
export default {};
</script>

<style scoped>
#todoFooter {
    height: 40px;
}

#todoFooter button {
    width: 30%;
    height: 90%;

    border: solid 2px lightskyblue;
    border-radius: 8px;

    background-color: lightskyblue;

    font-size: 1em;
    color: white;

    float: right;
}

#todoFooter button:hover {
    border: solid 2px cornflowerblue;
    background-color: cornflowerblue;
}
</style>

<template>

  • Footer 영역을 지정하기 위해 <div> 태그 사용 및 id 정의
  • 'Delete All' 버튼을 사용하기 위해 <button> 태그 사용

<style>

  • #todoFooter button → 전체 삭제 버튼에 대한 CSS 효과 지정
    • ':hover'  = 마우스를 해당 요소 위에 올려두었을 때 변화된 스타일을 보여주도록 속성 지정
    • 우측 하단에 표시되도록 'float: right' 속성 부여

 

src\components\Practice\Todo\TodoInput.vue

위 Layout 구조에서 TodoInput 컴포넌트를 정의하는 파일을 구현합니다.

결과 이미지에서 보여지는 바와 같이 TodoInput에는 텍스트 입력 필드와 추가 버튼이 존재합니다.

<!-- TodoInput.vue -->

<template>
    <div id="todoInput">
        <input  type="text"
                placeholder="Todo로 관리할 사항을 입력하세요."/>
        <button>+</button>
    </div>
</template>

<script>
export default {};
</script>

<style scoped>
#todoInput {
    height: 50px;

    display: flex;
    justify-content: center;
    align-content: center;

    margin: 5px;
    padding: 5px;

    border: solid 2px lightgray;
    border-radius: 8px;
}

#todoInput input[type="text"] {
    width: 90%;
    height: 90%;
    padding: 0px 0px 0px 5px;
    
    border: none;
    font-size: 1.1em;
}

#todoInput input[type="text"]:focus {
    outline: none;
}

#todoInput button {
    width: 10%;
    height: 90%;

    border: solid 2px lightcoral;
    border-radius: 8px;

    background-color: lightcoral;

    font-size: 1em;
    color: white;
}

#todoInput button:hover {
    border: solid 2px tomato;
    background-color: tomato;
}
</style>

<template>

  • Input 영역을 지정하기 위해 <div> 태그 사용 및 id 정의
  • 텍스트를 입력받기 위해 <input type="text"> 태그 사용 및 도움말 문구인 placeholder 지정
  • 추가 버튼을 사용하기 위해 <button> 태그 사용

<style>

  • #todoInput: Input 필드에 대한 속성 및 하위 요소(<input>, <button>)의 정렬 지정
  • #todoInput input[type="text"]: 입력 필드에 대한 CSS 효과 지정
    • ':focus' = 입력 필드 선택(마우스 클릭, 등)시 표시되는 필드 라인을 제거하기 위한 속성 지정
  • #todoInput button: 추가 버튼에 대한 CSS 효과 지정
    • ':hover'  = 마우스를 해당 요소 위에 올려두었을 때 변화된 스타일을 보여주도록 속성 지정

 

src\components\Practice\Todo\TodoList.vue

위 Layout 구조에서 TodoList 컴포넌트를 정의하는 파일을 구현합니다.

결과 이미지에서 보여지는 바와 같이 TodoList에는 체크박스와 입력 텍스트 그리고 삭제 버튼이 존재합니다.

<!-- TodoList.vue -->

<template>
    <div id="todoList">
        <li>
            <input type="checkbox">
            <span> todo </span>
            <button>x</button>
        </li>
    </div>
</template>

<script>
export default {};
</script>

<style scoped>
#todoList li {
    display: flex;
    justify-content: center;
    align-content: center;

    border: dotted 2px lightslategray;
    border-radius: 8px;

    margin: 3px;
    padding: 3px;
}

#todoList li input[type="checkbox"] {
    width: 5%;
    float: left;

    accent-color: gray;
}

input[type="checkbox"]:checked + span {
    text-decoration: line-through;
    color: gray;
    font-style: italic;
}

#todoList li span {
    width: 85%;
}

#todoList li button {
    width: 10%;
    float: right;

    border: solid 2px lightgrey;
    border-radius: 8px;

    background-color: lightgrey;

    font-size: 1em;
    color: white;
}

#todoList li button:hover {
    border: solid 2px darkgray;
    background-color: darkgray;
}
</style>

<template>

  • List 영역을 지정하기 위해 <div> 태그 사용 및 id 정의
  • 체크박스를 표현하기 위해 <input type="checkbox"> 태그 사용 
  • 입력받은 텍스트를 표시하기 위해 <span> 태그 사용
  • 삭제 버튼을 사용하기 위해 <button> 태그 사용

<style>

  • #todoList li: List 필드의 하위 요소인 <li> 태그에 대한 CSS 효과 지정
  • #todoList li input[type="checkbox"]: 체크박스에 대한 CSS 효과 지정
    • ':checked' = 체크박스 선택(체크)시 변경될 CSS 효과 지정
  • #todoList li span: 입력된 결과로 표시될 텍스트에 대한 CSS 효과 지정
  • #todoList li button: 삭제 버튼에 대한 CSS 효과 지정
    • ':hover'  = 마우스를 해당 요소 위에 올려두었을 때 변화된 스타일을 보여주도록 속성 지정

 

src\views\Practice\PracticeTodo.vue

위 결과 이미지에서 하얀색으로 표시되는 Todo List의 전체 영역 및 하위 컴포넌트를 정의하고 관리하는 코드를 구현합니다. 

<template>
    <div id="todo">
        <TodoHeader></TodoHeader>
        <TodoInput></TodoInput>
        <TodoList></TodoList>
        <TodoFooter></TodoFooter>
    </div>
</template>

<script>
import TodoHeader from "../../components/Practice/Todo/TodoHeader.vue";
import TodoInput from "../../components/Practice/Todo/TodoInput.vue";
import TodoList from "../../components/Practice/Todo/TodoList.vue";
import TodoFooter from "../../components/Practice/Todo/TodoFooter.vue";

export default {
    components: {
        TodoHeader,
        TodoInput,
        TodoList,
        TodoFooter
    }
};
</script>

<style scoped>
</style>

<template>

  • Todo List의 하위 컴포넌트로 사용될 TodoHeader, TodoInput, TodoList, TodoFooter에 대해서 순차적으로 정의하는 코드
  • Todo List의 최상위 영역을 Layout으로 지정하기 위해 <div> 로 한 번 감싸도록 선언

<script>

  • <template> 영역에서 사용할 하위 컴포넌트를 import 및 components로 선언하는 코드 

 

src\App.vue & public\index.html

위 결과 이미지에서 보여지는 텍스트의 폰트를 정의하는 코드를 구현합니다.

자세한 사항은 아래 게시글을 참조하시기 바랍니다.

https://logs-jejustone.tistory.com/39

 

 


References

 

HTML Tutorial

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

CSS Tutorial

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

Quick Start | Vue.js

 

vuejs.org

댓글