Vue/Do it! Vue.js 입문

06 실전 애플리케이션 만들기(2)

원Fe이 2023. 3. 4. 20:25

06 - 5 기존 애플리케이션 구조의 문제점 해결하기

지금까지 구현한 애플리케이션의 문제점은 다음 2가지 입니다.

- 할 일을 입력했을 때 할 일 목록에 바로 반영되지 않는 점

- 할 일을 모두 삭제했을 때 할 일 목록에 바로 반영되지 않는 점

 

종합해 보면 현재 화면은 4개의 영역(컴포넌트)으로 분리해 놓았기 때문에 한 영역의 처리 결과를 다른 영역에서 감지하지 못한다는 문제가 있습니다.

 

이 문제점을 해결하는 가장 간단한 방법은 컴포넌트를 4개로 분리하지 않고 한 컴포넌트 안에서 데이터 저장, 조회, 삭제를 모두 처리하는 것입니다. 그러면 컴포넌트 간에 처리 결과를 알려줄 필요도 없고 깔끔하게 뷰의 반응성이 적용되어 할 일 목록이 데이터의 입출력에 따라 항상 최신 상태를 유지하겠죠. 하지만 과연 이게 옳은 해결책 인가요?

 

곰곰히 생각해 보면 컴포넌트 기반의 웹 앱이 커지면 커질수록 컴포넌트의 개수도 많아지는 것은 불가피합니다.

지금처럼 간단한 애플리케이션일 때 컴포넌트 통신을 할 수 있어야 향후에 스스로 애플리케이션을 설계하고 구현할 수 있습니다.

 

App.vue 파일 data, methods를 추가한다

app.vue

app.vue 컴포넌트 안에 props와 이벤트 발생을 추가한다.

app.vue

TodoInput 컴포넌트에서 + 버튼을 클릭하면 app.js로 이벤트가 가도록 작성을 한다.

TodoInput.vue

app.vue 에서는 하위 컴포넌트에서 이벤트가 발생시 동작해야될 메소드를 작성한다.

app.vue

TodoList 컴포넌트의 <template>를 수정한다.

TodoList.vue

App.vue 에서 propsdata를 넘겨받고 TodoList.vue에서 props : ["propsdata"] 받고

v-for 반복문에 todoitems를 propsdata로 변경한다. 그리고 한가지 삭제하는 removeTodo를 이벤트 발생시켜 App.vue에서 객체를 삭제하게 만들도록 $emit()으로 이벤트를 발생시키게 한다.

App.vue

컴포넌트에 @removeTodo="removeTodo" 를 작상한 후 App.vue removeTodo 메소드를 작성한다. 

 

TodoFooter.vue 컴포넌트에는

removeAll 메소드가 있기때문에 역시 이벤트를 발생하는 $emit()를 작성한후 app.vue 컴포넌트에서 발생하면 실행되는 메소드를 작성하면 된다.

App.vue
App.vue

 

06 - 6 더 나은 사용자 경험을 위한 기능 추가하기

앞에서 제작한 기능에 이어서 사용자 경험을 향상시키는 2가지 기능을 추가로 구현해 보겠습니다.

현재 애플리케이션은 화면이 리액티브하게 동작하기 때문에 할 일을 추가했을 때 목록의 맨 아래에 추가된 아이템이 갑자기 나타납니다. 할 일을 삭제할 때도 마찬가지로 목록에 아이템이 불쑥 사라지기 때문에 어떤 아이템을 삭제했는지 놓치기 쉽습니다. 또한 할 일에 입력 값이 없는데 + 버튼을 누르는 경우 아무 이벤트가 발생하지 않기 때문에 자칫 오류가 있는 애플리케이션으로 착각할 수 있습니다. 그러면 애니미메이션과 모달을 이용하여 애플리케이션의 완성도를 높여 봅시다.

 

뷰 애니메이션

뷰 애니메이션은 뷰 프레임워크 자체에서 지원하는 애니메이션 기능으로, 데이터 추가, 변경, 삭제에 대해서 페이드 인(fade in), 페이드 아웃(fade out) 등의 여러 가지 애니메이션 효과를 지원합니다.

 

기존에 ul태그를 제거하고 transition-group 태그를 추가합니다. tag 속성에 애니메이션이 들어갈 HTML 태그 이름을 지정하면 됩니다. name속성은 이후 추가할 css 클래스와 연관이 있습니다.

TodoList.vue

그리고 li 태그에 v-bind:key를 간략하게 표현한 :key를 추가합니다. 목록에 애니메이션을 적용하려면 <transition-group>안의 대상 태그에 :key속성을 꼭 지정해야 하기 때문입니다. :key속성에는 유일하게 구분되는 값을 넣어야 하는데 여기서는 일단 todoItem이라는 텍스트 값을 사용합니다.

 

:key속성은 v-for 디렉티브를 사용할 때 지정하는게 좋습니다.

뷰는 목록의 특정 아이템이 삭제되거나 추가되었을 때, 돔에서 나머지 아이템의 순서를 다시 조정하지 않고 프레임워크 내부적으로 전체 아이템의 순서를 제어합니다. 이렇게 프레임워크에서 목록 아이템의 순서를 제어하는 이유는 브라우저가 돔을 조작하는 데 소요되는 시간들을 최소화하기 위해서입니다.

css를 추가해 줍니다.

 

뷰 모달

아무것도 입력을 하지 않고 + 버튼을 클릭 또는 , enter 키를 입력을 했을때 모달창을 띄우겠습니다.

components 폴더 안에 common 폴더를 한개더 생성한다.

common 폴더 안에 ModalView.vue 파일을 생성한다.

(처음에 Modal.vue로 생성했는데 오류 나길래 찾아보니 파일명을 대문자 두개가 들어가야 한다고 해서 View를 추가했다.)

TodoInput.vue

Modal 컴포넌트를 입력한다.

Modal 컴포넌트 안의 내용은 https://vuejs.org/examples/#modal 여기에 있따.

TodoInput.vue

import를 받고 components 에 입력을 하고 data 안에 showModal = false 로 작성을 한다.

처음에 false로 값으로 해둔 이유는 첫화면에 안보이게 하기 위해서 이다.

addTodo가 실행이 되었고 false이면 실행이되게 작성한다.

 

아무리 눌러도 모달창이 뜨지 않아서

ModalView의 script안에 props를 지우고 data를 입력해서 보이게 만들었다.

ModalView.vue 컴포넌트가 true가 되어도 안보이길래

보니깐 div v-if가 되어 있어서 항상 보이게 show를 true를 줬다.

(그냥 div태그안에 v-if를 지우면 되구나...ㅎ)

ModalView.vue
ModalView.vue
결과 화면

이렇게 완성이 되었다.

그리고 현재 애플리케이션은 할일 추가, 조회, 삭제만 가능합니다. 변경은 구현하지 않았는데, 현재 코드에서 어떻게 하면 할 일 목록에 등록된 데이터를 변경할 수 있을지 한번 고민해 보기 바랍니다. 라고 적혀 있다.

 

내 생각에는 모르겠다. list 컴포넌트에 클릭 이벤트를 만들고 input 컴포넌트에 해당 item을 로컬스토리지 안에서 받아 props 하면 되겠지라고 생각했는데 아닌거 같다.