반응형

Vue.js의 생성주기(lifecycle)는 Vue 인스턴스가 생성되어 DOM에 렌더링되고, 데이터가 변경되어 업데이트되는 과정에서 호출되는 일련의 메서드들입니다. 이 생성주기 훅들을 활용하면, 컴포넌트의 특정 단계에서 로직을 실행할 수 있습니다.

 

Vue 2와 Vue 3 모두 유사한 생성주기를 가지지만, Vue 3에서는 Composition API가 도입되면서 라이프사이클 훅이 약간 다른 형태로 사용됩니다. 여기서는 Options API와 Composition API 두 가지 스타일 모두에서 생성주기를 어떻게 활용하는지 설명하겠습니다.

 

1. Vue 인스턴스의 생명주기 (Options API 기준)

 

Vue 컴포넌트는 다음과 같은 주요 생명주기 단계를 거칩니다:

 

1) Before Create (beforeCreate)

 

설명: Vue 인스턴스가 초기화되기 전, data와 methods가 정의되기 전에 호출됩니다.

용도: 초기화 전에 실행할 코드를 작성할 수 있지만, data나 methods에 접근할 수 없습니다.

beforeCreate() {
  console.log('beforeCreate: 데이터와 메서드가 정의되기 전입니다.');
}

2) Created (created)

 

설명: Vue 인스턴스가 생성된 후, data와 methods가 초기화된 상태에서 호출됩니다. 이 시점에서 인스턴스는 반응형 상태입니다.

용도: API 호출, 초기 데이터 설정 등의 작업을 할 수 있습니다. 하지만 DOM에 접근할 수 없습니다.

created() {
  console.log('created: 인스턴스가 생성되고 data와 methods가 초기화되었습니다.');
}

3) Before Mount (beforeMount)

 

설명: 템플릿이 렌더링되기 전에 호출됩니다. DOM에 접근할 수 있지만, 아직 Vue가 DOM에 연결되지 않은 상태입니다.

용도: 렌더링 전에 DOM에 대해 작업할 필요가 있을 때 사용할 수 있습니다.

beforeMount() {
  console.log('beforeMount: 템플릿이 렌더링되기 전입니다.');
}

4) Mounted (mounted)

 

설명: Vue 인스턴스가 DOM에 마운트된 후 호출됩니다. 이 시점에서 템플릿은 DOM에 반영되었으며, 컴포넌트가 화면에 나타납니다.

용도: 컴포넌트가 DOM에 연결된 후 초기화 작업을 하거나, 외부 라이브러리를 초기화할 때 사용할 수 있습니다.

mounted() {
  console.log('mounted: 인스턴스가 DOM에 마운트되었습니다.');
}

5) Before Update (beforeUpdate)

 

설명: 반응형 데이터가 변경되어 DOM이 업데이트되기 직전에 호출됩니다.

용도: 데이터가 변경되었지만 DOM에 반영되기 전에 작업을 수행할 수 있습니다.

beforeUpdate() {
  console.log('beforeUpdate: 데이터가 변경되었고 DOM이 업데이트되기 전입니다.');
}

6) Updated (updated)

 

설명: 데이터가 변경되어 DOM이 다시 렌더링된 후 호출됩니다.

용도: 데이터 변경에 따른 DOM 작업을 수행할 수 있습니다.

updated() {
  console.log('updated: 데이터가 변경되고 DOM이 업데이트되었습니다.');
}

7) Before Destroy (beforeDestroy)

 

설명: Vue 인스턴스가 파괴되기 전에 호출됩니다.

용도: 인스턴스가 파괴되기 전에 정리 작업을 수행할 수 있습니다. 이벤트 리스너 해제, 타이머 제거 등이 필요할 때 사용합니다.

beforeDestroy() {
  console.log('beforeDestroy: 인스턴스가 파괴되기 전입니다.');
}

8) Destroyed (destroyed)

 

설명: Vue 인스턴스가 파괴된 후 호출됩니다. 인스턴스의 모든 바인딩과 이벤트 리스너가 해제됩니다.

용도: 인스턴스 파괴 후의 작업을 수행할 수 있습니다.

destroyed() {
  console.log('destroyed: 인스턴스가 파괴되었습니다.');
}

2. Vue 3에서의 Composition API 생성주기

 

Vue 3에서는 Composition API가 도입되면서 라이프사이클 훅도 setup 함수 내에서 사용할 수 있도록 변경되었습니다. 각 훅은 Vue 2의 Options API에서와 동일한 시점에 호출되지만, 이름이 조금씩 다릅니다.

 

onBeforeMount: beforeMount와 동일한 타이밍에 호출됩니다.

onMounted: mounted와 동일한 타이밍에 호출됩니다.

onBeforeUpdate: beforeUpdate와 동일한 타이밍에 호출됩니다.

onUpdated: updated와 동일한 타이밍에 호출됩니다.

onBeforeUnmount: beforeDestroy와 동일한 타이밍에 호출됩니다.

onUnmounted: destroyed와 동일한 타이밍에 호출됩니다.

 

import { onMounted, onBeforeUnmount } from 'vue';

export default {
  setup() {
    onMounted(() => {
      console.log('mounted: 컴포넌트가 마운트되었습니다.');
    });

    onBeforeUnmount(() => {
      console.log('beforeUnmount: 컴포넌트가 파괴되기 전입니다.');
    });
  }
};

3. 생성주기 훅의 활용 예시

 

API 호출

 

created 또는 onMounted에서 초기 데이터를 가져오기 위해 API를 호출할 수 있습니다.

created() {
  fetch('/api/data')
    .then(response => response.json())
    .then(data => {
      this.data = data;
    });
}

// Composition API 방식
onMounted(() => {
  fetch('/api/data')
    .then(response => response.json())
    .then(data => {
      state.data = data;
    });
});

DOM 초기화

 

외부 라이브러리나 플러그인을 초기화하기 위해 mountedonMounted를 사용할 수 있습니다.

mounted() {
  this.$nextTick(() => {
    this.initializePlugin();
  });
}

// Composition API 방식
onMounted(() => {
  nextTick(() => {
    initializePlugin();
  });
});

4. 결론

 

Vue의 생명주기는 컴포넌트의 생성, 렌더링, 업데이트, 파괴 과정에서 특정 시점에 코드 실행을 가능하게 합니다. Options API에서는 메서드 형태로 각 훅을 정의하며, Composition API에서는 setup 함수 내부에서 훅을 호출하는 방식으로 관리합니다. 이 생성주기 훅들은 컴포넌트의 초기화, DOM 접근, 외부 자원 관리, 데이터 업데이트 등에 중요한 역할을 합니다.


생성주기 문서

https://ko.vuejs.org/guide/essentials/lifecycle.html

반응형

'프론트엔드 > Vuejs' 카테고리의 다른 글

vue to-do 리스트 구현 7 - composition api 비교  (0) 2024.08.18
Vuetify 문서 레퍼런스 가이드  (0) 2024.08.17
vue vuex 란  (0) 2024.08.17
vue to-do 리스트 구현 6 - vuex 구현  (0) 2024.08.17
Vue Router란?  (0) 2024.08.17
반응형

 

1. Option API와 Composition API 비교 설명

 

Option API:

전통적인 Vue.js 방식으로, 컴포넌트의 로직을 data, methods, computed, watch 등으로 구분합니다.

코드의 구조가 명확하게 나누어져 있어, 이해하기 쉬운 것이 장점입니다.

큰 컴포넌트에서는 로직이 흩어져 있어 관리가 어려워질 수 있습니다.

Composition API:

Vue 3에서 도입된 새로운 방식으로, 함수형 프로그래밍 스타일에 가까운 접근법입니다.

관련 로직을 setup 함수 내에서 함께 정의할 수 있어, 큰 컴포넌트에서도 관련 로직을 그룹화하여 관리할 수 있습니다.

ref, computed, watch, onMounted 등의 기능을 활용하여 상태와 라이프사이클을 관리합니다.

코드 재사용성이 높아지며, 특히 큰 프로젝트에서 유리합니다.

 

Composition API를 사용하여 post 게시판을 구현하면서 기존의 Option API 방식과 비교할 수 있었습니다. Composition API는 보다 유연하고 코드 재사용성을 높이는 데 유리하며, Vuex와의 결합도 자연스럽습니다. 이를 통해 학생들이 Vue의 두 가지 API 스타일을 이해하고, 필요에 따라 적절히 선택할 수 있도록 도울 수 있습니다.

todoList 를 postList 로 동일한 코드로 composition api 로 변형 해보았습니다. 


PostList.vue

<template>
    <v-container>
      <v-row>
        <v-col>
          <h1>Vue.js Post Board</h1>
          <AddPost @add-post="addPost" />
          <v-list>
            <v-list-item
              v-for="(post, index) in posts"
              :key="index"
              @click="navigateToDetail(index)"
            >
              <template v-slot:prepend>
                <v-checkbox
                  v-model="post.completed"
                  @click.stop="togglePostStatus(index, !post.completed)"
                  hide-details
                />
              </template>
              
              <v-list-item-title>{{ post.text }}</v-list-item-title>
              
              <template v-slot:append>
                <v-btn icon="mdi-delete" size="small" @click.stop="removePost(index)">
                </v-btn>
              </template>
            </v-list-item>
          </v-list>
        </v-col>
      </v-row>
    </v-container>
  </template>
  
  <script>
  import { computed, onMounted } from 'vue';
  import { useRouter } from 'vue-router';  // useRouter를 import
  import { useStore } from 'vuex';
  import AddPost from './AddPost.vue';
  
  export default {
    name: 'PostList',
    components: { AddPost },
    setup() {
      const store = useStore();
      const router = useRouter();
  
      const posts = computed(() => store.getters.posts);
      const addPost = (postText) => store.dispatch('addPost', postText);
      const removePost = (index) => store.dispatch('removePost', index);
      const togglePostStatus = (index, completed) =>
        store.dispatch('togglePostStatus', { index, completed });
  
      const navigateToDetail = (index) => {
        // Navigate to post detail page
        router.push({ name: 'PostDetail', params: { id: index } });
      };
  
      onMounted(() => {
        store.dispatch('loadPosts');
      });
  
      return {
        posts,
        addPost,
        removePost,
        togglePostStatus,
        navigateToDetail,
      };
    },
  };
  </script>

 

AddPost.vue

<template>
    <v-text-field
      v-model="newPost"
      label="Add a new post"
      @keyup.enter="submitPost"
      outlined
      dense
    />
    <v-btn color="primary" @click="submitPost">Add</v-btn>
  </template>
  
  <script>
  import { ref } from 'vue';
  
  export default {
    name: 'AddPost',
    emits: ['add-post'],  // 커스텀 이벤트를 정의합니다.
    setup(props, { emit }) {
      const newPost = ref('');
  
      const submitPost = () => {
        if (newPost.value.trim()) {
          emit('add-post', newPost.value);
          newPost.value = '';
        }
      };
  
      return {
        newPost,
        submitPost,
      };
    },
  };
  </script>

 

PostDetail.vue

<template>
    <v-container>
      <h2>Post Detail</h2>
      <v-card>
        <v-card-text>
          <p>ID: {{ id }}</p>
          <p v-if="post">Text: {{ post.text }}</p>
          <p v-else>Post not found</p>
        </v-card-text>
      </v-card>
      <v-btn @click="$router.push('/post')">Back</v-btn>
    </v-container>
  </template>
  
  <script>
  import { computed } from 'vue';
  import { useStore } from 'vuex';
  import { useRoute } from 'vue-router';
  
  export default {
    setup() {
      const store = useStore();
      const route = useRoute();
  
      const id = computed(() => route.params.id);
      const post = computed(() => store.getters['posts'][id.value]);
  
      return {
        id,
        post,
      };
    },
  };
  </script>

 

 

이전에 만들었던 todo List 와 비교하면서 보면 이해가 빠를 겁니다. 



2. Composition API 구성 요소

 

1) setup 함수

 

setup 함수는 Composition API의 핵심으로, 컴포넌트가 생성될 때 호출됩니다. 이 함수 내에서 상태 관리, 메서드 정의, 라이프사이클 훅 등을 설정할 수 있습니다.

 

리턴값: setup 함수에서 반환하는 객체는 템플릿에서 사용됩니다. 이 함수에서 정의한 모든 데이터와 메서드는 setup의 반환 객체를 통해 템플릿에서 접근 가능합니다.

 

2) useStore와 useRouter

 

useStore: Vuex의 스토어에 접근하기 위해 사용됩니다. store 객체를 반환하며, 이를 통해 상태 관리와 관련된 모든 작업을 수행할 수 있습니다.

useRouter: Vue Router에서 제공하는 훅으로, 현재 라우터 인스턴스에 접근하여 라우팅을 처리할 수 있습니다. 예를 들어, 페이지 이동을 위해 router.push를 사용할 수 있습니다.

 

3) computed

 

computed 속성은 반응형 데이터를 정의할 때 사용됩니다. 여기서 posts는 Vuex 스토어에서 가져온 할 일 목록으로, computed로 선언하여 Vue의 반응형 시스템과 연결됩니다.

 

4) onMounted

 

onMounted는 Vue의 라이프사이클 훅 중 하나로, 컴포넌트가 DOM에 마운트된 직후 호출됩니다. 이 훅을 사용하여 컴포넌트가 초기화될 때 필요한 작업을 수행할 수 있습니다. 예를 들어, 이 코드에서는 컴포넌트가 마운트될 때 loadPosts 액션을 디스패치하여 로컬 스토리지에서 데이터를 불러옵니다.

3. 구현된 기능 설명

 

Post 목록 가져오기 (posts): posts는 Vuex의 getters.postscomputed로 받아와, 템플릿에서 렌더링됩니다.

Post 추가하기 (addPost): 사용자가 새로운 포스트를 추가하면, 해당 텍스트가 Vuex 액션을 통해 posts 상태에 추가됩니다.

Post 상태 토글 (togglePostStatus): 체크박스를 클릭하여 포스트의 완료 상태를 토글할 수 있습니다. 이 상태는 v-modelstore.dispatch를 통해 Vuex와 동기화됩니다.

Post 삭제하기 (removePost): 삭제 버튼을 클릭하면 해당 포스트가 삭제됩니다. 이 작업 역시 Vuex 액션을 통해 처리됩니다.

Post 상세보기 페이지로 이동 (navigateToDetail): 포스트 항목을 클릭하면 해당 포스트의 상세 페이지로 라우팅됩니다. router.push를 통해 PostDetail 페이지로 이동하며, id 파라미터를 전달합니다.

 

4. Composition API와 Options API 비교

 

유연성: Composition API는 로직과 상태 관리를 한 곳에 모아서 정의할 수 있으므로, 관련된 코드를 쉽게 그룹화하고 재사용할 수 있습니다.

재사용성: Composition API는 함수로 로직을 캡슐화하여 재사용할 수 있어, 복잡한 컴포넌트에서 더 나은 코드 조직화를 제공합니다.

명확성: setup 함수 안에서 모든 로직을 관리하므로, 상태와 메서드가 어디에서 정의되고 어떻게 사용되는지 명확히 알 수 있습니다.


이전 블로그 
vuex 를 이용한 todo list 작성
https://juntcom.tistory.com/323 

 

vue 가이드 - option, composition api 
https://ko.vuejs.org/guide/introduction.html

 

반응형

'프론트엔드 > Vuejs' 카테고리의 다른 글

vue lifecycle 라이프사이클 정리  (0) 2024.08.18
Vuetify 문서 레퍼런스 가이드  (0) 2024.08.17
vue vuex 란  (0) 2024.08.17
vue to-do 리스트 구현 6 - vuex 구현  (0) 2024.08.17
Vue Router란?  (0) 2024.08.17
반응형

Vuetify는 Material Design 가이드를 따르는 Vue.js UI 라이브러리로, 다양한 사전 제작된 컴포넌트와 유틸리티를 제공하여 반응형이고 미적으로 우수한 인터페이스를 빠르게 개발할 수 있도록 도와줍니다. 아래는 Vuetify를 효과적으로 사용하는 데 필요한 주요 개념과 문서에 대한 가이드입니다.

 

Vuetify 시작하기

 

설치

공식 설치 가이드: Vuetify 설치

vue add vuetify

 

npm install vuetify

 

설치 후 main.js 파일에서 Vuetify를 설정합니다:

import { createApp } from 'vue';
import App from './App.vue';
import vuetify from './plugins/vuetify';

createApp(App)
  .use(vuetify)
  .mount('#app');

 

스타일링 및 레이아웃

Vuetify는 Material Design의 레이아웃 시스템을 따릅니다. v-container, v-row, v-col을 사용하여 반응형 레이아웃을 쉽게 구성할 수 있습니다.

 

v-container: 레이아웃의 기본 컨테이너로, 내부에 v-rowv-col을 포함합니다.

v-row: 수평 행을 생성하며, 여러 v-col을 포함할 수 있습니다.

v-col: 열을 생성하며, 그리드 시스템에서 비율에 따라 폭을 차지합니다.

<v-container>
  <v-row>
    <v-col cols="12" md="8">Main content</v-col>
    <v-col cols="12" md="4">Sidebar</v-col>
  </v-row>
</v-container>

 

 

텍스트 크기 및 타이포그래피

 

Vuetify는 text-h1에서 text-h6까지 다양한 텍스트 스타일과 크기를 제공하며, 이러한 클래스들을 사용해 쉽게 텍스트 스타일을 적용할 수 있습니다.

문서: 텍스트 및 타이포그래피

<v-typography variant="h1">This is a headline</v-typography>
<v-typography variant="body-1">This is body text</v-typography>

 

컬러 팔레트

 

Vuetify는 Material Design을 기반으로 한 색상 팔레트를 포함하고 있어, 애플리케이션 전반에 걸쳐 일관된 색상 테마를 쉽게 적용할 수 있습니다.

문서: Material Colors

 

아이콘 폰트

 

Vuetify는 다양한 아이콘 폰트를 지원하며, Material Design Icons(MDI)와 쉽게 통합할 수 있습니다.

아이콘 검색 및 사용: Vuetify 아이콘 폰트

MDI 전체 라이브러리 보기: MDI 아이콘 라이브러리

 

테마 커스터마이징

 

Vuetify에서 애플리케이션의 테마를 커스터마이징할 수 있습니다. 테마 값은 myCustomLightTheme 객체를 수정하여 변경할 수 있습니다.

문서: 테마 설정

const vuetify = createVuetify({
  theme: {
    themes: {
      light: {
        primary: '#3f51b5',
        secondary: '#b0bec5',
        accent: '#8c9eff',
        error: '#b71c1c',
      },
    },
  },
});

 

 

컬러 속성

 

Vuetify의 컬러 속성을 사용하여 Material Design의 색상 시스템으로 컴포넌트를 스타일링할 수 있습니다.

문서: 컬러 속성

 

간격(Spacing) 유틸리티

 

Vuetify는 마진과 패딩을 쉽게 관리할 수 있는 간격 유틸리티를 제공합니다.

문서: 간격 유틸리티

 

그리드 시스템 (Col 속성)

 

Vuetify의 그리드 시스템은 Flexbox를 기반으로 하며, 강력한 레이아웃 시스템을 제공합니다.

문서: 그리드 및 Col 속성

 

컴포넌트

 

텍스트 필드

 

텍스트 필드는 사용자로부터 텍스트 입력을 받기 위한 주요 폼 요소입니다.

문서: 텍스트 필드

<v-form>
  <v-text-field label="Name" v-model="name"></v-text-field>
  <v-select :items="['Option 1', 'Option 2']" label="Select an option"></v-select>
  <v-checkbox label="Accept Terms" v-model="accepted"></v-checkbox>
</v-form>

 

 

라디오 버튼

 

라디오 버튼은 목록에서 하나의 옵션을 선택할 때 사용됩니다.

문서: 라디오 버튼

 

다이얼로그(Dialog)

 

다이얼로그는 중요한 정보나 사용자의 결정을 요청하는 모달 창입니다.

예시: 다이얼로그 사용법

<v-dialog v-model="dialog">
  <v-card>
    <v-card-title>Dialog Title</v-card-title>
    <v-card-text>
      This is a dialog content.
    </v-card-text>
    <v-card-actions>
      <v-btn @click="dialog = false">Close</v-btn>
    </v-card-actions>
  </v-card>
</v-dialog>

 

 

데이터 테이블

 

데이터 테이블은 구조화된 데이터를 표 형식으로 표시하는 데 사용되며, 정렬, 페이징, 검색 등의 기능을 제공합니다.

문서: 데이터 테이블

<v-data-table :headers="headers" :items="items" :search="search">
  <template v-slot:top>
    <v-text-field v-model="search" label="Search"></v-text-field>
  </template>
</v-data-table>

 

카드

 

카드는 다양한 유형의 콘텐츠를 표시하는 데 유용한 유연한 컨테이너입니다.

예시: 카드 사용법

<v-card>
  <v-card-title>Card Title</v-card-title>
  <v-card-subtitle>Card Subtitle</v-card-subtitle>
  <v-card-text>
    This is some text within a card.
  </v-card-text>
  <v-card-actions>
    <v-btn text>Action</v-btn>
  </v-card-actions>
</v-card>

 

 

셀렉트 입력

 

셀렉트 입력은 목록에서 옵션을 선택할 수 있도록 합니다.

문서: 셀렉트 입력

 

내비게이션 드로어

 

내비게이션 드로어는 사이드 메뉴를 제공하며, 토글로 표시하거나 숨길 수 있습니다.

문서: 내비게이션 드로어

 

리스트

 

리스트는 관련된 콘텐츠를 그룹화하여 표시하는 데 사용됩니다.

문서: 리스트

 

 

칩은 복잡한 엔티티를 컴팩트한 형태로 표현하는 작은 컴포넌트입니다.

예시: 칩 사용법

API 문서: v-chip API

 

반응형

'프론트엔드 > Vuejs' 카테고리의 다른 글

vue lifecycle 라이프사이클 정리  (0) 2024.08.18
vue to-do 리스트 구현 7 - composition api 비교  (0) 2024.08.18
vue vuex 란  (0) 2024.08.17
vue to-do 리스트 구현 6 - vuex 구현  (0) 2024.08.17
Vue Router란?  (0) 2024.08.17
반응형

Vuex는 Vue.js 애플리케이션에서 상태 관리를 중앙 집중화할 수 있도록 도와주는 공식적인 상태 관리 패턴 및 라이브러리입니다.

Vuex를 사용하면 애플리케이션의 상태를 중앙에서 관리하고, 이를 다양한 컴포넌트들이 공유할 수 있습니다.

Vuex는 특히 규모가 큰 애플리케이션에서 컴포넌트 간의 상태 관리를 단순화하고, 일관된 상태 관리를 가능하게 합니다.

 

Vuex의 주요 개념

 

1. State (상태)

state는 애플리케이션의 중앙에서 관리되는 상태를 정의합니다. Vue 컴포넌트의 data와 유사하지만, 여러 컴포넌트가 공유할 수 있는 중앙 집중식 상태입니다.

const store = createStore({
  state: {
    todos: []
  },
});

2. Mutations (변이)

mutations는 상태를 변경하는 메서드입니다. 상태를 변경할 때는 반드시 mutations를 통해 변경해야 합니다. 이는 Vuex의 핵심 개념 중 하나로, 상태 변이를 추적하고 디버깅을 쉽게 만들어줍니다.

mutations: {
  setTodos(state, todos) {
    state.todos = todos;
  },
  addTodo(state, todo) {
    state.todos.push(todo);
  },
  removeTodo(state, index) {
    state.todos.splice(index, 1);
  },
  updateTodoStatus(state, { index, completed }) {
    state.todos[index].completed = completed;
  }
}

3. Actions (액션)

actionsmutations와 유사하지만, 비동기 작업을 처리할 수 있습니다. 액션은 mutations를 커밋하여 상태를 변경합니다. 예를 들어, API 호출 후 응답 데이터를 상태에 반영하는 작업을 actions에서 처리합니다.

 

actions: {
  loadTodos({ commit }) {
    const savedTodos = localStorage.getItem('todos');
    if (savedTodos) {
      commit('setTodos', JSON.parse(savedTodos));
    }
  },
  saveTodos({ state }) {
    localStorage.setItem('todos', JSON.stringify(state.todos));
  },
  addTodo({ commit, dispatch }, todoText) {
    const newTodo = { text: todoText, completed: false };
    commit('addTodo', newTodo);
    dispatch('saveTodos');
  },
  removeTodo({ commit, dispatch }, index) {
    commit('removeTodo', index);
    dispatch('saveTodos');
  },
  toggleTodoStatus({ commit, dispatch }, payload) {
    commit('updateTodoStatus', payload);
    dispatch('saveTodos');
  }
}

 

4. Getters (게터)

getters는 상태에서 값을 가져올 때 사용됩니다. Vue 컴포넌트에서 computed 속성과 유사하게 동작합니다. 상태를 가공하거나 필터링하여 반환할 수 있습니다.

getters: {
  todos(state) {
    return state.todos;
  }
}

5. Store (스토어)

Vuex store는 Vuex의 중심입니다. 상태(state), 변이(mutations), 액션(actions), 게터(getters) 등을 포함하여 애플리케이션의 전체 상태를 관리합니다. 컴포넌트는 이 스토어를 통해 중앙 상태에 접근하고, 변경할 수 있습니다.

import { createStore } from 'vuex';

const store = createStore({
  state: {
    todos: []
  },
  mutations: { /* 변이들 */ },
  actions: { /* 액션들 */ },
  getters: { /* 게터들 */ }
});

export default store;

 

 

 

 

 

 

Vuex의 사용 예시

 

다음은 Vuex를 활용하여 To-Do 리스트 애플리케이션의 상태를 관리하는 방법에 대한 예시입니다.

 

1. 상태 정의 및 초기화

todos 배열을 상태로 정의하고, 로컬 스토리지에서 저장된 할 일 목록을 불러와 todos에 저장합니다.

state: {
  todos: []
}

2. 상태 업데이트

사용자가 새로운 할 일을 추가하거나, 할 일의 상태를 변경하면 Vuex의 mutations를 통해 상태가 업데이트됩니다.

mutations: {
  addTodo(state, todo) {
    state.todos.push(todo);
  },
  updateTodoStatus(state, { index, completed }) {
    state.todos[index].completed = completed;
  }
}

3. 액션을 통한 상태 관리

actions를 통해 비동기 작업과 상태 변이를 처리합니다. 예를 들어, 로컬 스토리지에 할 일 목록을 저장하는 작업은 actions에서 처리됩니다.

actions: {
  saveTodos({ state }) {
    localStorage.setItem('todos', JSON.stringify(state.todos));
  }
}

4. 컴포넌트에서 Vuex 상태 접근

컴포넌트에서는 mapGetters, mapActions를 사용하여 Vuex 상태와 메서드를 간단히 연결할 수 있습니다.

<script>
import { mapGetters, mapActions } from 'vuex';

export default {
  computed: {
    ...mapGetters(['todos'])
  },
  methods: {
    ...mapActions(['addTodo', 'toggleTodoStatus', 'removeTodo'])
  }
}
</script>

요약

 

중앙 집중화된 상태 관리: Vuex를 사용하면 상태를 중앙에서 관리하여 컴포넌트 간의 상태 공유와 변경을 쉽게 추적할 수 있습니다.

예측 가능한 상태 관리: 모든 상태 변경은 mutations를 통해 이루어지므로, 상태 변경을 쉽게 예측하고 디버깅할 수 있습니다.

비동기 작업 관리: 비동기 작업은 actions를 통해 관리되어, 복잡한 비동기 로직도 쉽게 처리할 수 있습니다.

Vue 컴포넌트와의 통합: mapGettersmapActions를 통해 Vue 컴포넌트와 Vuex 상태 및 메서드를 간단히 연결할 수 있습니다.

 

Vuex는 규모가 큰 애플리케이션에서 특히 유용하며, 상태를 일관되게 유지하고 컴포넌트 간의 상태 관리 복잡성을 줄여줍니다.

반응형
반응형

Vuex를 사용하여 To-Do 리스트 애플리케이션을 리팩토링하는 방법을 설명하겠습니다.

Vuex는 Vue.js 애플리케이션에서 상태 관리를 중앙에서 처리할 수 있도록 도와주는 라이브러리입니다.

이 예제에서는 Vuex를 사용하여 할 일 목록(todos)을 중앙에서 관리하고, 컴포넌트들이 Vuex 스토어를 통해 상태를 접근하고 수정하도록 하겠습니다.

 

1. Vuex 설치

 

먼저 Vuex를 설치해야 합니다.

npm install vuex@next

2. Vuex 스토어 설정 (store/index.js)

 

src/store/index.js 파일을 생성하고, Vuex 스토어를 설정합니다.

import { createStore } from 'vuex'

const store = createStore({
  state: {
    todos: []
  },
  mutations: {
    setTodos(state, todos) {
      state.todos = todos;
    },
    addTodo(state, todo) {
      state.todos.push(todo);
    },
    removeTodo(state, index) {
      if (index >= 0 && index < state.todos.length) {
        state.todos.splice(index, 1);
      }
    },
    updateTodoStatus(state, { index, completed }) {
      if (index >= 0 && index < state.todos.length) {
        state.todos[index].completed = completed;
      }
    }
  },
  actions: {
    loadTodos({ commit }) {
      const savedTodos = localStorage.getItem('todos');
      if (savedTodos) {
        commit('setTodos', JSON.parse(savedTodos));
      }
    },
    saveTodos({ state }) {
      localStorage.setItem('todos', JSON.stringify(state.todos));
    },
    addTodo({ commit, dispatch }, todoText) {
      const newTodo = { text: todoText, completed: false };
      commit('addTodo', newTodo);
      dispatch('saveTodos');
    },
    removeTodo({ commit, dispatch }, index) {
      commit('removeTodo', index);
      dispatch('saveTodos');
    },
    toggleTodoStatus({ commit, dispatch }, payload) {
      const { index, completed } = payload;
      console.log('toggleTodoStatus', index, completed);
      commit('updateTodoStatus', { index, completed });
      dispatch('saveTodos');
    }
  },
  getters: {
    todos(state) {
      return state.todos;
    }
  }
});

export default store;

3. Vue 애플리케이션에 Vuex 추가 (main.js)

 

main.js 파일에서 Vuex 스토어를 Vue 애플리케이션에 추가합니다.

import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import { loadFonts } from './plugins/webfontloader'
import router from './router'  // Vue Router를 추가
import store from './store'  // Vuex 스토어를 가져옵니다.


loadFonts()

createApp(App)
  .use(vuetify)
  .use(router)  // Vue Router 사용
  .use(store)  // Vuex 스토어를 사용합니다.
  .mount('#app')

4. ToDoList.vue 컴포넌트 수정

 

이제 ToDoList.vue 컴포넌트를 수정하여 Vuex 스토어에서 상태를 가져오고, 할 일을 추가 및 삭제하는 기능을 구현합니다.

<template>
  <v-container>
    <v-row>
      <v-col>
        <h1>Vue.js To-Do App</h1>
        <AddTodo @add-todo="addTodo" />
        <v-list>
          <v-list-item
            v-for="(todo, index) in todos"
            :key="index"
            @click="$router.push({ name: 'ToDoDetail', params: { id: index } })"
          >
            <template v-slot:prepend>
              <v-checkbox
                v-model="todo.completed"
                @click.stop="toggleTodoStatus({ index, completed: !todo.completed })"
                hide-details
              />
            </template>
            
            <v-list-item-title>{{ todo.text }}</v-list-item-title>
            
            <template v-slot:append>
              <v-btn icon="mdi-delete" size="small" @click.stop="removeTodo(index)">
              </v-btn>
            </template>
          </v-list-item>
        </v-list>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import AddTodo from './AddTodo.vue'
import { mapActions, mapGetters } from 'vuex'

export default {
  name: 'ToDoList',
  components: { AddTodo },
  computed: {
    ...mapGetters(['todos'])  // Vuex에서 todos 상태를 가져옵니다.
  },
  methods: {
    ...mapActions(['addTodo', 'removeTodo', 'toggleTodoStatus']),  // Vuex 액션들을 가져옵니다.
  },
  created() {
    this.$store.dispatch('loadTodos')  // Vuex 스토어에서 할 일을 로드합니다.
  }
}
</script>

5. TodoDetail.vue 컴포넌트 수정

 

TodoDetail.vue에서 Vuex 상태를 사용하도록 수정합니다.

<template>
    <v-container>
      <h2>To-Do Detail</h2>
      <v-card>
        <v-card-text>
          <p>ID: {{ id }}</p>
          <p v-if="todo">Text: {{ todo.text }}</p>
          <p v-else>Todo not found</p>
        </v-card-text>
      </v-card>
      <v-btn @click="$router.push('/')">Back</v-btn>
    </v-container>
  </template>
  
  <script>
  import { mapGetters } from 'vuex'
  
  export default {
    props: {
      id: {
        type: String,
        required: true
      }
    },
    computed: {
      ...mapGetters(['todos']),
      todo() {
        return this.todos[this.id]
      }
    }
  }
  </script>

 

1. Vuex 상태 관리:

state: todos 배열을 중앙에서 관리합니다.

mutations: 상태를 직접적으로 변경하는 로직을 포함합니다(addTodo, removeTodo, updateTodoStatus).

actions: 비동기 작업이나 여러 변형을 처리하고, 상태를 변경하는 메서드를 포함합니다(loadTodos, saveTodos 등).

2. ToDoList.vue 컴포넌트:

computed: mapGetters를 통해 Vuex에서 todos 상태를 가져옵니다.

methods: mapActions를 통해 Vuex 액션을 사용하여 할 일을 추가, 삭제, 상태를 변경하고, 로컬 스토리지와 동기화합니다.

created: 컴포넌트가 생성될 때 loadTodos 액션을 호출하여 로컬 스토리지에서 저장된 할 일 목록을 불러옵니다.


이전 블로그

vue to-do 리스트 구현 5 - router 구현

https://juntcom.tistory.com/321 

반응형

'프론트엔드 > Vuejs' 카테고리의 다른 글

Vuetify 문서 레퍼런스 가이드  (0) 2024.08.17
vue vuex 란  (0) 2024.08.17
Vue Router란?  (0) 2024.08.17
vue to-do 리스트 구현 5 - router 구현  (0) 2024.08.17
vue to-do 리스트 구현 4 - vuetify 적용  (0) 2024.08.16
반응형

Vue Router란?

 

Vue Router는 Vue.js 애플리케이션에서 라우팅을 관리하는 공식 라이브러리입니다.

라우팅이란 사용자가 특정 URL을 요청했을 때, 그 URL에 맞는 페이지나 컴포넌트를 제공하는 기능을 말합니다.

Vue Router를 사용하면 단일 페이지 애플리케이션(SPA)에서 페이지 간 네비게이션을 쉽게 구현할 수 있습니다.

 

주요 개념과 기능

 

1. 라우터(Router)

Vue Router는 createRouter 함수를 사용하여 라우터 인스턴스를 생성합니다. 이 라우터 인스턴스는 애플리케이션의 경로(라우트)와 해당 경로에 연결된 컴포넌트들을 정의하는 곳입니다.

 

import { createRouter, createWebHistory } from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

위 코드에서 routes는 경로와 그 경로에 연결된 컴포넌트들의 배열입니다. 이 배열은 경로와 해당 경로에 접근할 때 표시할 컴포넌트를 매핑합니다.

 

2. 라우트(Route)

라우트는 URL과 해당 URL에서 렌더링할 컴포넌트를 매핑하는 객체입니다. 예를 들어, /about 경로에 접근하면 About 컴포넌트가 렌더링됩니다.

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

 

3. 라우터 히스토리 모드(History Mode)

Vue Router는 기본적으로 Hash 모드HTML5 History 모드를 지원합니다.

Hash 모드: URL에 #을 포함하여 경로를 구분합니다. 예: http://example.com/#/about. 브라우저에서 URL의 해시 부분은 서버로 전달되지 않기 때문에, 서버 측에서 추가 설정이 필요 없습니다.

HTML5 History 모드: URL에 해시(#) 없이 깔끔한 경로를 제공합니다. 예: http://example.com/about. 이 모드를 사용할 경우 서버 측 설정을 통해 모든 경로를 index.html로 리디렉션하도록 해야 합니다.

const router = createRouter({
  history: createWebHistory(), // HTML5 History 모드
  routes
})

 

4. 라우터 뷰(Router View)

router-view는 현재 활성화된 경로에 맞는 컴포넌트를 표시하는 Vue의 내장 컴포넌트입니다. 애플리케이션에서 이 컴포넌트를 어디에 두느냐에 따라, 해당 위치에 라우터에 의해 결정된 컴포넌트가 렌더링됩니다.

<template>
  <div>
    <router-view></router-view>
  </div>
</template>

 

5. 라우터 링크(Router Link)

router-link는 다른 페이지나 컴포넌트로 네비게이션할 수 있는 링크를 만드는 Vue의 내장 컴포넌트입니다. 이를 사용하면 HTML의 <a> 태그처럼 작동하지만, SPA 특성상 페이지 전체를 다시 로드하지 않고도 URL을 변경할 수 있습니다.

 

<template>
  <div>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
  </div>
</template>

 

6. 동적 라우트 매칭(Dynamic Route Matching)

동적 라우트 매칭은 URL 경로의 일부를 변수로 처리하여, 다양한 URL 패턴에 대해 하나의 컴포넌트를 사용할 수 있게 합니다. 예를 들어, 블로그 포스트 페이지를 생각해 볼 수 있습니다.

const routes = [
  { path: '/posts/:id', component: PostDetail }
]

여기서 :id는 동적 세그먼트로, 실제로는 posts/1, posts/2 등의 URL이 이 경로와 매칭됩니다. 이 idpropsthis.$route.params를 통해 컴포넌트에서 접근할 수 있습니다.

 

7. 네비게이션 가드(Navigation Guards)

네비게이션 가드는 특정 경로에 접근하기 전에 실행되는 함수로, 라우팅을 허용할지, 막을지, 또는 리다이렉트할지를 결정합니다. 이를 통해 인증이 필요한 페이지에 대한 접근을 제어할 수 있습니다.

전역 가드: 모든 경로 변경에 대해 적용됩니다.

라우트별 가드: 특정 라우트에만 적용됩니다.

컴포넌트 내 가드: 컴포넌트 내에서 정의되고, 해당 컴포넌트가 활성화될 때 적용됩니다.

router.beforeEach((to, from, next) => {
  if (to.path === '/protected' && !isAuthenticated) {
    next('/login')
  } else {
    next()
  }
})

 

8. 중첩된 라우트(Nested Routes)

Vue Router는 중첩된 라우트를 지원합니다. 이는 라우트가 중첩된 컴포넌트를 렌더링할 수 있도록 해줍니다.

const routes = [
  { 
    path: '/user/:id', 
    component: User,
    children: [
      { path: 'profile', component: UserProfile },
      { path: 'posts', component: UserPosts }
    ]
  }
]

이 경우, UserProfile이나 UserPosts 컴포넌트는 User 컴포넌트의 내부에 렌더링됩니다.

 

결론

 

Vue Router는 Vue.js 애플리케이션에서 페이지 간 이동을 관리하고, URL을 통해 상태를 관리할 수 있는 강력한 도구입니다. 이를 통해 SPA에서의 복잡한 네비게이션 구조를 간편하게 관리할 수 있으며, 사용자 경험을 향상시키는 데 매우 유용합니다. Vue Router를 잘 이해하고 사용하면, Vue.js 애플리케이션의 네비게이션과 상태 관리를 훨씬 더 효율적으로 수행할 수 있습니다.

반응형
반응형

Vue Router는 Vue.js 애플리케이션에서 라우팅을 관리하는 공식 라이브러리입니다.

라우팅이란 사용자가 특정 URL을 요청했을 때, 그 URL에 맞는 페이지나 컴포넌트를 제공하는 기능을 말합니다.

Vue Router를 사용하면 단일 페이지 애플리케이션(SPA)에서 페이지 간 네비게이션을 쉽게 구현할 수 있습니다.



1. Vue Router 설치

 

먼저 Vue Router를 프로젝트에 설치해야 합니다.

 

npm install vue-router@next

이 명령어는 Vue 3용 Vue Router를 설치합니다. 설치가 완료되면 Vue Router를 프로젝트에 추가할 수 있습니다.

 

2. 라우터 설정 (router/index.js)

 

프로젝트의 src 디렉토리 아래에 router 폴더를 만들고, 그 안에 index.js 파일을 생성합니다. 이 파일에서 라우터를 설정합니다.

import { createRouter, createWebHistory } from 'vue-router'
import ToDoList from '../components/ToDoList.vue'
import TodoDetail from '../components/TodoDetail.vue'

const routes = [
  { path: '/', name: 'Home', component: ToDoList },
  { path: '/todo/:id', name: 'TodoDetail', component: TodoDetail, props: true }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

createRouter: Vue 3에서 라우터를 생성하는 함수입니다.

createWebHistory: HTML5의 history 모드를 사용하는 함수로, 브라우저의 URL을 깔끔하게 유지합니다.

routes: 경로와 그에 연결된 컴포넌트를 정의하는 배열입니다.

props: true: 라우트 파라미터를 컴포넌트의 props로 전달할 때 사용합니다.

 

3. 라우터를 Vue 애플리케이션에 추가 (main.js)

 

이제 main.js 파일에서 Vue 애플리케이션에 라우터를 추가해야 합니다.

import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import { loadFonts } from './plugins/webfontloader'
import router from './router'  // Vue Router를 가져옵니다.

loadFonts()

createApp(App)
  .use(vuetify)
  .use(router)  // Vue Router를 사용합니다.
  .mount('#app')

여기서 router를 Vue 애플리케이션에 use하여 라우터를 활성화합니다.

 

4. App.vue에서 라우터 뷰 설정

 

App.vue 파일에서 router-view 컴포넌트를 사용하여 현재 라우터에 맞는 컴포넌트를 렌더링할 수 있도록 설정합니다.

<template>
  <v-app>
    <v-container>
      <router-view />  <!-- 라우터가 렌더링할 컴포넌트가 여기에 표시됩니다. -->
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: 'App',
}
</script>

router-view: Vue Router에서 제공하는 컴포넌트로, 현재 라우트에 맞는 컴포넌트를 렌더링합니다.

 

5. 페이지 컴포넌트 작성

 

각 라우트에 연결된 컴포넌트를 작성합니다. 예를 들어, ToDoList.vueTodoDetail.vue 파일을 작성합니다.

 

ToDoList.vue

<template>
  <v-container>
    <v-row>
      <v-col>
        <h1>Vue.js To-Do App</h1>
        <AddTodo @add-todo="addTodo" />
        <v-list>
          <v-list-item
            v-for="(todo, index) in todos"
            :key="index"
            @click="$router.push({ name: 'ToDoDetail', params: { id: index } })"
          >
            <template v-slot:prepend>
              <v-checkbox
                v-model="todo.completed"
                @change="saveTodos"
                hide-details
              />
            </template>
            
            <v-list-item-title>{{ todo.text }}</v-list-item-title>
            
            <template v-slot:append>
              <v-btn icon="mdi-delete" size="small" @click.stop="removeTodo(index)">
              </v-btn>
            </template>
          </v-list-item>
        </v-list>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import AddTodo from './AddTodo.vue'

export default {
  name: 'ToDoList',
  components: { AddTodo },
  data() {
    return {
      todos: []
    }
  },
  mounted() {
    const savedTodos = localStorage.getItem('todos')
    if (savedTodos) {
      this.todos = JSON.parse(savedTodos)
    }
  },
  methods: {
    addTodo(newTodo) {
      this.todos.push({ text: newTodo, completed: false })
      this.saveTodos()
    },
    removeTodo(index) {
      this.todos.splice(index, 1)
      this.saveTodos()
    },
    saveTodos() {
      localStorage.setItem('todos', JSON.stringify(this.todos))
    }
  }
}
</script>

$router.push: 사용자가 클릭할 때 특정 라우트로 이동합니다.

params: { id: index }: 라우트 파라미터로 id를 전달합니다.

 

ToDoDetail.vue

<template>
  <v-container>
    <h2>To-Do Detail</h2>
    <v-card>
      <v-card-text>
        <p>ID: {{ id }}</p>
      </v-card-text>
    </v-card>
    <v-btn @click="$router.push('/')">Back</v-btn>
  </v-container>
</template>

<script>
export default {
  props: {
    id: {
      type: String,
      required: true
    }
  }
}
</script>

props: { id }: 라우트 파라미터로 전달된 id를 컴포넌트에서 사용합니다.


이전 블로그
vue to-do 리스트 구현 4 - vuetify 적용

https://juntcom.tistory.com/319

반응형
반응형

Vuetify는 Vue.js 기반의 Material Design 컴포넌트 프레임워크로, 반응형 UI를 쉽게 만들 수 있습니다.

기존의 To-Do 리스트 애플리케이션에 Vuetify를 적용하여 스타일을 개선하고, Vuetify의 컴포넌트를 활용하여 UI를 향상시켜보겠습니다.

 

1. Vuetify 설치

먼저 Vuetify를 프로젝트에 설치합니다.

1. 터미널에서 Vuetify 설치:

vue add vuetify

vue add vuetify 를 할 경우 4가지 선택지가 나오는데
vuetify2 를 할 것인지, 그리고 vue-cli 를 할 것인지에 대한 선택지가 나오는데
vuetify3 및 vite 라는 빌드툴을 사용하기로 했습니다. (최신버젼이기 때문) 

Vuetify 3 + Vite의 장점

A. 빠른 빌드 속도:

Vite는 빌드 도구로서 매우 빠른 속도를 자랑합니다. 특히 개발 중에 실시간으로 코드 변경 사항을 반영하는 속도가 빠르기 때문에, 대규모 프로젝트에서 매우 유용합니다.

Vite는 기본적으로 ES 모듈을 기반으로 작동하므로, 빌드 과정이 간소화되고 빠릅니다.

B. 최신 기능:

Vuetify 3는 Vuetify의 최신 버전으로, 최신 Vue.js 기능들을 활용할 수 있습니다. 특히, Composition API와 함께 사용할 때 더욱 강력한 기능을 제공합니다.

Vuetify 3은 새로운 디자인 시스템과 개선된 컴포넌트 구조를 제공하여 UI 개발에 더 나은 경험을 제공합니다.

C. 미래 지향적:

Vite와 Vuetify 3은 모두 Vue.js 커뮤니티에서 적극적으로 지원하는 최신 도구들입니다. 이를 사용하면 최신 기술을 습득하고 미래의 프로젝트에서 활용할 준비를 할 수 있습니다.

 

Vuetify 3 + Vite의 단점 및 고려사항

A. 호환성 문제:

Preview 단계: Vuetify 3은 아직 preview 단계이므로, 일부 기능이 불안정할 수 있으며, 공식적으로 모든 기능이 완전히 지원되지 않을 수 있습니다.

플러그인 호환성: Vuetify 3과 Vite를 사용하면, 기존의 일부 Vue.js 플러그인 또는 Vuetify 2에서 사용하던 플러그인들이 호환되지 않을 수 있습니다.

B. 러닝 커브:

Vite는 Webpack과는 다른 접근 방식을 취하기 때문에, 기존에 Webpack에 익숙한 개발자라면 Vite의 설정과 동작 방식에 적응하는 데 약간의 시간이 걸릴 수 있습니다.

C. 안정성:

Vite와 Vuetify 3의 조합은 최신 기술 스택이기 때문에, 프로젝트에 사용하기 전에 충분한 테스트가 필요할 수 있습니다. 대규모 프로젝트나 프로덕션 환경에서 사용할 때는 사전 검토가 중요합니다.



2.
프로젝트 실행:

설치가 완료된 후, 프로젝트를 다시 실행하여 Vuetify가 정상적으로 적용되었는지 확인합니다.

npm run dev

 

1). App.vue에서 Vuetify 레이아웃 적용

Vuetify의 기본 레이아웃 컴포넌트인 v-app, v-container, v-row, v-col 등을 사용하여 레이아웃을 설정합니다.

<template>
  <v-app>
    <v-container>
      <v-row>
        <v-col>
          <h1 class="text-center">Vue.js To-Do App</h1>
          <AddTodo @add-todo="addTodo" />
          <ToDoList :todos="todos" @remove-todo="removeTodo" @save-todos="saveTodos" />
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
import AddTodo from './components/AddTodo.vue';
import ToDoList from './components/ToDoList.vue';

export default {
  name: 'App',
  components: {
    AddTodo,
    ToDoList
  },
  data() {
    return {
      todos: []
    };
  },
  mounted() {
    const savedTodos = localStorage.getItem('todos');
    if (savedTodos) {
      this.todos = JSON.parse(savedTodos);
    }
  },
  methods: {
    addTodo(newTodo) {
      this.todos.push({ text: newTodo, completed: false });
      this.saveTodos();
    },
    removeTodo(index) {
      this.todos.splice(index, 1);
      this.saveTodos();
    },
    saveTodos() {
      localStorage.setItem('todos', JSON.stringify(this.todos));
    }
  }
};
</script>

<style>
.text-center {
  text-align: center;
}
</style>

3. AddTodo.vue에 Vuetify 컴포넌트 적용

 

AddTodo.vue 컴포넌트에서 Vuetify의 입력 및 버튼 컴포넌트를 사용합니다.

<template>
    <v-row class="mb-3">
      <v-col>
        <v-text-field
          v-model="newTodo"
          label="Add a new to-do"
          outlined
          dense
          @keyup.enter="submitTodo"
        />
      </v-col>
      <v-col cols="auto">
        <v-btn color="primary" @click="submitTodo">Add</v-btn>
      </v-col>
    </v-row>
  </template>
  
  <script>
  export default {
    name: 'AddTodo',
    data() {
      return {
        newTodo: ''
      };
    },
    methods: {
      submitTodo() {
        if (this.newTodo.trim()) {
          this.$emit('add-todo', this.newTodo);
          this.newTodo = '';
        }
      }
    }
  };
  </script>



4. TodoList.vue에 Vuetify 컴포넌트 적용

 

TodoList.vue 컴포넌트에서도 Vuetify의 리스트, 체크박스, 버튼 컴포넌트를 사용합니다.

<template>
  <v-list>
    <v-list-item
      v-for="(todo, index) in todos"
      :key="index"
      :class="{ 'completed': todo.completed }"
    >
      <v-row align="center" no-gutters>
        <v-col cols="auto" class="mr-3">
          <v-checkbox
            v-model="todo.completed"
            @change="saveTodos"
            hide-details
          />
        </v-col>
        <v-col>
          <v-list-item-content>
            <v-list-item-title>{{ todo.text }}</v-list-item-title>
          </v-list-item-content>
        </v-col>
        <v-col cols="auto">
          <v-btn icon small @click="removeTodo(index)">
            <v-icon>mdi-delete</v-icon>
          </v-btn>
        </v-col>
      </v-row>
    </v-list-item>
  </v-list>
</template>

<script>
export default {
  name: 'TodoList',
  props: {
    todos: {
      type: Array,
      required: true
    }
  },
  methods: {
    removeTodo(index) {
      this.$emit('remove-todo', index);
    },
    saveTodos() {
      this.$emit('save-todos');
    }
  }
};
</script>

<style scoped>
.completed .v-list-item__title {
  text-decoration: line-through;
  color: grey;
}
</style>

 

 

전체 코드 요약

 

App.vue

Vuetify의 레이아웃 컴포넌트(v-app, v-container, v-row, v-col)을 사용하여 구조를 만듭니다.

 

AddTodo.vue

Vuetify의 v-text-fieldv-btn을 사용하여 입력 필드와 버튼을 구현합니다.

 

TodoList.vue

Vuetify의 v-list, v-checkbox, v-btn, v-icon을 사용하여 할 일 리스트와 삭제 버튼을 구현합니다.

이전 블로그 

 

반응형

+ Recent posts