그랜파 개발자의 프론트엔드 공부-Vue

Vue로 PWA 개발, ChatGPT의 프론트엔드 앱 Router 예제를 실행해 봅시다.

그랜파 개발자 2024. 11. 30. 04:06

Vue로 PWA 개발 - 그랜파 개발자.

 

ChatGPT가 제공한 예제인 Vuetify와 함께 Vue Router를 사용하여

페이지 라우팅 기능이 포함되어 있고,

App Bar, Drawer, Footer를 포함한 UI를 가진 앱을 실행하여 봅니다.
예제를 실행하도록 하는 과정에서 약간의 수정된 내용이 있습니다.

 

그림 27-1

1. Vue 프로젝트 만들기

vue create my-pwa-app

 

? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, PWA, Router, Vuex
? Choose a version of Vue.js that you want to start the project with 2.x
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? (y/N) n

2. vuetify 설치

cd my-pwa-app

vue add vuetify

 

? Choose a preset: (Use arrow keys)
Vuetify 2 - Configure Vue CLI (advanced)
> Vuetify 2 - Vue CLI (recommended)
Vuetify 2 - Prototype (rapid development)
Vuetify 3 - Vite (preview)
Vuetify 3 - Vue CLI (preview)

3. 라우터 설정

라우터는 프로젝트에 추가하는 방식이 ChatGPT의 예제와는 달라 프로젝트 만들기에서 주어진 코드를 수정하였습니다.

// src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue';
import About from '@/views/About.vue';
import Contact from '@/views/Contact.vue';

Vue.use(VueRouter)

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

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

4. 메인 파일에 라우터 추가

프로젝트를 만들 때 router를 선택하였으므로 이미 추가되어 있습니다.

// src/main.js
import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  vuetify,
  render: h => h(App)
}).$mount('#app')

5. 페이지 컴포넌트 생성

Home.vue

<!-- src/views/Home.vue -->
<template>
  <v-container>
    <h1>Home</h1>
    <p>Welcome to the Home page!</p>
  </v-container>
</template>

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

About.vue

<!-- src/views/About.vue -->
<template>
  <v-container>
    <h1>About</h1>
    <p>Learn more about us on this page.</p>
  </v-container>
</template>

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

Contact.vue

<!-- src/views/Contact.vue -->
vue
코드 복사
<template>
  <v-container>
    <h1>Contact</h1>
    <p>Get in touch with us!</p>
  </v-container>
</template>

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

6. App.vue 수정

<!-- src/App.vue -->
<template>
  <v-app>
    <!-- App Bar -->
    <v-app-bar color="primary" dark>
      <v-app-bar-nav-icon @click="toggleDrawer" />
      <v-toolbar-title>My App</v-toolbar-title>
    </v-app-bar>

    <!-- Navigation Drawer -->
    <v-navigation-drawer v-model="drawer" app>
      <v-list>
        <v-list-item-group>
          <v-list-item
            v-for="(item, index) in menuItems"
            :key="index"
            @click="navigateTo(item)"
          >
            <v-list-item-icon>
              <v-icon>{{ item.icon }}</v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title>{{ item.title }}</v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-navigation-drawer>

    <!-- Main Content -->
    <v-main>
      <router-view /> <!-- 라우터가 여기에 컴포넌트를 렌더링 -->
    </v-main>

    <!-- Footer -->
    <v-footer app color="secondary" dark>
      <v-container>
        <p>&copy; {{ new Date().getFullYear() }} My App. All rights reserved.</p>
      </v-container>
    </v-footer>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      drawer: false,
      menuItems: [
        { title: 'Home', icon: 'mdi-home', path: '/' },
        { title: 'About', icon: 'mdi-information', path: '/about' },
        { title: 'Contact', icon: 'mdi-phone', path: '/contact' },
      ],
    };
  },
  methods: {
    toggleDrawer() {
      this.drawer = !this.drawer;
    },
    navigateTo(item) {
      this.drawer = false; // 메뉴 클릭 시 Drawer 닫기
      // 같은 페이지를 라우팅하면 에러가 발생한다.
      if(this.$route.name !== item.title )    
        this.$router.push(item.path);
    },
  },
};
</script>

 

Vue 프로젝트 Beta Test : mylog, 일상의 기록