Blue Chicken - The Legend Of Zelda
본문 바로가기

개인공부

[vuetify3] vuecli 버전 적용하기 (v-app, v-main)

됐다...! v-main이 꼭 v-app 바로 밑에 올 필요는 없음 v-app만 전체를 감싸면 되고!

<!-- vuecli -->
<template>
  <!-- 최상위 태그 -->
  <v-app>
    
      <v-card>
        <!-- 정렬관리 -->
        <v-layout class="centered-content"> <!-- 중앙 정렬 클래스 적용 -->
          <v-app-bar color="primary" prominent>
            <v-app-bar-nav-icon @click.stop="toggleDrawer"></v-app-bar-nav-icon>
            <v-toolbar-title>vuePrac's applying vuecli</v-toolbar-title>
            <v-spacer></v-spacer>
            <!-- 반응형 -->
            <template v-if="$vuetify.display.mdAndUp">
              <v-btn icon="mdi-magnify" variant="text"></v-btn>
              <v-btn icon="mdi-filter" variant="text"></v-btn>
            </template>
            <v-btn icon="mdi-dots-vertical" variant="text"></v-btn>
          </v-app-bar>
          <v-navigation-drawer v-model="drawer" temporary>
            <v-list>
              <!-- 각 항목에 router-link를 사용하여 라우팅 -->
              <v-list-item v-for="item in items" :key="item.title" @click="navigate(item.value)">
                <v-list-item-title>{{ item.title }}</v-list-item-title>
              </v-list-item>
            </v-list>
          </v-navigation-drawer>
          <!-- 컨텐츠 영역 -->
          <v-main> 
            <!-- 본문 -->
            <v-card-text>
              <router-view/>
            </v-card-text>
          </v-main>
        </v-layout>
      </v-card>
    
  </v-app>
</template>

<script setup>
//import Navigation from '@/components/NavComponent.vue';



import { ref } from 'vue'; // Vue에서 필요한 모듈 가져오기
import { useRouter } from 'vue-router'; // Vue Router 인스턴스 가져오기

const router = useRouter(); // 라우터 인스턴스 생성
const drawer = ref(false); // 반응형 데이터
const items = [
  { title: 'TimeGame', value: '/timeGame' }, // 라우팅 경로 설정
  { title: 'Search', value: '/search' },
  { title: 'FactorialSetup', value: '/factorialSetup' },
  { title: 'Home', value: '/' },
]; // 목록 항목 정의

// 드로어 토글
const toggleDrawer = () => {
  drawer.value = !drawer.value;
};

// 라우터로 지정된 경로로 이동
const navigate = (route) => {
  router.push(route); // 지정된 경로로 라우팅
  drawer.value = false; // 드로어 닫기
};
</script>
<style>
#v-app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  height: 100%;
  
}

#router-view {
  height: 3000px;
  margin-top: 300px;
}

.centered-content {
  display: flex; 
  justify-content: center;  /* 수평 중앙 정렬 */
  align-items: center;     /* 수직 중앙 정렬 */
  /* height: 100%;            /* 부모 높이만큼 확장 */
}

</style>
  • <v-app>은 Vuetify 애플리케이션의 루트 컴포넌트로, 모든 Vuetify 컴포넌트가 이 안에서 동작해야 합니다.
  • <v-main>은 애플리케이션의 주요 콘텐츠 영역을 나타내며, 페이지의 주 콘텐츠가 이곳에 배치됩니다.
  • <v-card>: Vuetify의 카드 컴포넌트로, 모듈식 디자인과 다양한 콘텐츠 요소를 제공하며, 유연한 스타일링이 가능합니다.
  • <v-layout>: 레이아웃 컴포넌트로, 수평 또는 수직 정렬 및 정렬 방식과 간격을 조절하는 기능을 제공합니다.
  •  

문제 해결 이전 메모..

 

`v-app`, `v-main`, `v-layout`는 Vuetify의 레이아웃 구성 컴포넌트로, 애플리케이션의 구조와 계층을 만드는 데 사용됩니다. 각 컴포넌트는 Vue.js 애플리케이션의 특정 부분을 담당하며, 서로 관계를 맺고 있습니다.

### `v-app`
- **루트 컴포넌트**: `v-app`는 Vuetify 기반 애플리케이션의 루트 컴포넌트입니다. 모든 Vuetify 컴포넌트는 이 내부에서 동작해야 합니다.
- **전역 컨텍스트**: Vuetify의 전반적인 설정과 스타일링 컨텍스트를 제공합니다. 테마, 레이아웃, 색상, 반응형 디자인 등의 전역 설정을 제어합니다.

### `v-main`
- **주요 콘텐츠 영역**: `v-main`는 애플리케이션의 메인 콘텐츠 영역을 나타냅니다. 일반적으로 `v-app` 내부에 위치하며, 애플리케이션의 주요 콘텐츠를 렌더링하는 공간입니다.
- **레이아웃 구조**: `v-main`은 화면 레이아웃을 결정하며, 다른 Vuetify 컴포넌트와 함께 동작하여 전체 레이아웃을 구성합니다.

### `v-layout`
- **레이아웃 관리**: `v-layout`은 자식 요소의 정렬, 방향, 간격 등을 제어하는 데 사용됩니다. 수평(`row`) 또는 수직(`column`) 방향으로 설정할 수 있습니다.
- **정렬 및 간격 제어**: `v-layout`은 `justify-content`, `align-items` 등을 통해 자식 요소 간의 정렬과 간격을 제어합니다.

### 관계
- **`v-app`가 최상위**: `v-app`은 애플리케이션의 루트 컴포넌트로, 모든 Vuetify 컴포넌트는 이 내부에 위치해야 합니다.
- **`v-main`가 콘텐츠 영역**: `v-app` 내부에 위치하며, 애플리케이션의 주요 콘텐츠를 렌더링합니다. 
- **`v-layout`가 정렬 관리**: `v-main`이나 `v-card` 등의 내부에 위치하며, 자식 요소의 정렬과 레이아웃을 관리합니다.

### 예시
```vue
<template>
  <v-app> <!-- 루트 컴포넌트 -->
    <v-main> <!-- 주요 콘텐츠 영역 -->
      <v-layout row> <!-- 수평 레이아웃 -->
        <!-- 콘텐츠 요소들 -->
      </v-layout>
    </v-main>
  </v-app>
</template>
```

### 요약
- **`v-app`**은 Vuetify 기반 애플리케이션의 루트 컴포넌트로, 전역 컨텍스트를 제공합니다.
- **`v-main`**은 주요 콘텐츠 영역으로, 애플리케이션의 주요 내용을 렌더링합니다.
- **`v-layout`**은 레이아웃 관리 컴포넌트로, 자식 요소의 정렬 및 간격을 제어합니다.

이러한 관계를 이해하면, Vuetify를 사용하여 애플리케이션의 레이아웃과 구조를 효과적으로 구성할 수 있습니다.

 


더보기

문제의 코드

v-main은 Vuetify의 컴포넌트 중 하나로, 애플리케이션의 주요 콘텐츠 영역을 나타냅니다. 일반적으로 v-mainv-app 내에 한 번만 사용하며, 여러 개의 v-main이 필요하지 않습니다.

<!-- vuecli -->
<template>
  <!-- 최상위 태그 -->
  <v-app>
    <!-- 컨텐츠 영역 -->
    <v-main> 
      <v-card>
        <!-- 정렬관리 -->
        <v-layout class="centered-content"> <!-- 중앙 정렬 클래스 적용 -->
          <v-app-bar color="primary" prominent>
            <v-app-bar-nav-icon @click.stop="toggleDrawer"></v-app-bar-nav-icon>
            <v-toolbar-title>vuePrac's applying vuecli</v-toolbar-title>
            <v-spacer></v-spacer>
            <template v-if="$vuetify.display.mdAndUp">
              <v-btn icon="mdi-magnify" variant="text"></v-btn>
              <v-btn icon="mdi-filter" variant="text"></v-btn>
            </template>
            <v-btn icon="mdi-dots-vertical" variant="text"></v-btn>
          </v-app-bar>
          <v-navigation-drawer v-model="drawer" temporary>
            <v-list>
              <!-- 각 항목에 router-link를 사용하여 라우팅 -->
              <v-list-item v-for="item in items" :key="item.title" @click="navigate(item.value)">
                <v-list-item-title>{{ item.title }}</v-list-item-title>
              </v-list-item>
            </v-list>
          </v-navigation-drawer>
            <v-main style="height: 500px;">
              <v-card-text>
                <router-view/>
              </v-card-text>
            </v-main>
          
        </v-layout>
      </v-card>
    </v-main>
  </v-app>
</template>

<script setup>
//import Navigation from '@/components/NavComponent.vue';



import { ref } from 'vue'; // Vue에서 필요한 모듈 가져오기
import { useRouter } from 'vue-router'; // Vue Router 인스턴스 가져오기

const router = useRouter(); // 라우터 인스턴스 생성
const drawer = ref(false); // 반응형 데이터
const items = [
  { title: 'TimeGame', value: '/timeGame' }, // 라우팅 경로 설정
  { title: 'Search', value: '/search' },
  { title: 'FactorialSetup', value: '/factorialSetup' },
  { title: 'Home', value: '/' },
]; // 목록 항목 정의

// 드로어 토글
const toggleDrawer = () => {
  drawer.value = !drawer.value;
};

// 라우터로 지정된 경로로 이동
const navigate = (route) => {
  router.push(route); // 지정된 경로로 라우팅
  drawer.value = false; // 드로어 닫기
};
</script>
<style>
#v-app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  height: 100%;
  
}
#v-main{
  
}
#v-layout {
  height: 100%;
}

.centered-content {
  display: flex; 
  justify-content: center;  /* 수평 중앙 정렬 */
  align-items: center;     /* 수직 중앙 정렬 */
  height: 100%;            /* 부모 높이만큼 확장 */
}

</style>