Vue.js 3.0 Router 사용하기

|

Vue.js 3.0 Router 예제

Routing 기능은 특정 페이지로 이동하는 기능입니다.


설치 방법

npm install vue-router@4

또는

yarn add vue-router@4

간단한 예제

다음은 Vue Router를 설치하면 기본적으로 생성되는 예제입니다. <router-link> 태그 안에 Routing된 페이지가 출력됩니다.

Routing을 위해 <a> 태그를 이용해도 되지만, 이 경우 전체 페이지가 리로딩이 되는데, <router-link>를 이용할 경우 전체 페이지 리로딩 없이 <router-link> 안에 Routing된 페이지를 출력할 수 있습니다.

App.vue

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

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

nav {
  padding: 30px;
}

nav a {
  font-weight: bold;
  color: #2c3e50;
}

nav a.router-link-exact-active {
  color: #42b983;
}
</style>

router/index.js

Routing을 원하는 경로를 router/index.js에 추가하면 됩니다.

import { createRouter, createWebHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
import AboutView from "../views/AboutView.vue";

const routes = [
  {
    path: "/",
    name: "home",
    component: HomeView,
  },
  {
    path: "/about",
    name: "about",
    component: AboutView,
  },
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

export default router;

main.js

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

createApp(App).use(router).mount("#app");

Todo App의 Router 예제

간단한 Todo App을 만든다고 할 때 Router 기능 사용 예제입니다.

router/index.js

import { createRouter, createWebHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
import TodoListView from "../views/TodoListView.vue";
import TodoView from "../views/TodoView.vue";
import AboutView from "../views/AboutView.vue";

const routes = [
  {
    path: "/",
    name: "home",
    component: HomeView,
  },
  {
    path: "/about",
    name: "about",
    component: AboutView,
  },
  {
    path: "todos",
    name: "todos",
    component: TodoListView,
  },
  {
    path: "todos/:id",
    name: "todo",
    component: TodoView,
  },
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

export default router;

TodoListView.vue

router.push() 함수를 이용한 Routing

...
<script>
  setup() {
    ...
    const router = useRouter();
    const moveToPage = (todoId) => {
      router.push(`/todos/${todoId}`);
    }; 
  }
</script>

Routing Name을 이용한 Routing

...
<script>
  setup() {
    ...
    const router = useRouter();
    const moveToPage = (todoId) => {
      router.push({
        name: "Todo",
        params: {
          id: todoId
        }
      });
    }; 
  }
</script>

Vue.js 3.0 파일 구조

|

Vue.js 3.0 파일 구조

Single-File Components

Vue는 SFC(Single-File Components)로 되어 있습니다. 하나의 파일에 JavaScripts, Template, Style 모두 저장되어 있어 관리가 용이합니다.

vue 파일 구조

하나의 vue 파일의 구조는 다음과 같습니다. Vue 공식 홈페이지에서 더 자세히 확인할 수 있습니다

<script>
export default {
  data() {
    return {
      greeting: 'Hello World!'
    }
  }
}
</script>

<template>
  <p class="greeting"></p>
</template>

<style>
.greeting {
  color: red;
  font-weight: bold;
}
</style>

순서는 크게 상관은 없지만, Vue 공식 홈페이지 기준으로는 script, template, style 순으로 배치합니다.

vscode의 vue 자동 생성 템플릿 수정(Vetur 플러그인)

Vue 개발시 주로 vscodeVetur 플러그인을 많이 사용할텐데, 빈 문서에서 vue를 타이핑하고 엔터를 치면 Scaffolding 기능을 통해 다음과 같은 형태로 기본 문서가 만들어집니다.

image

<template>
  
</template>

<script>
export default {

}
</script>

<style>

</style>

이 부분을 공식 Vue 가이드 문서와 같은 형태로 변경하려면 다음과 같은 방법으로 해야 합니다.

현재 개발하는 프로젝트의 루트 디렉토리에서 .vscode/vetur/snippets 디렉토리 아래 vue3-default.vue 파일을 생성하고 아래 내용을 채웁니다.

<script setup>

</script>

<template>
  
</template>

<style scoped>

</style>

그 다음 vscode를 재실행하면 새로 추가한 Scaffold를 선택해서 초기 코드를 생성할 수 있습니다.

Vuetify 기본 레이아웃(App Bar)

|

Vuetify 기본 레이아웃

기본적으로 Material Design은 App BarContent로 이루어집니다. 여기에 Navigation Drawer가 추가되기도 합니다.


먼저 App Bar와 Content로 이루어진 레이아웃입니다.

<template>
  <v-app ref="app">
    <v-app-bar></v-app-bar>
    <v-main></v-main>
    <v-footer></v-footer>
  </v-app>
</template>

App Bar 꾸미기

이 중에서 App Bar는 다음과 같은 요소로 구성되어 있습니다.

image

  1. Container: v-app-bar로 생성되는 전체 영역 컨테이너
  2. App Bar Icon: v-app-bar-nav-icon로 추가
  3. Title: v-app-bar-title
  4. Action Items: v-btn icon
  5. Overflow menu: v-btn icon

간단한 App Bar

App Bar 태그 안에 v-btn icon 태그를 추가하면 자동으로 오른 정렬되어 추가가 됩니다. Overflow menu도 버튼의 아이콘만 다른 동일한 버튼입니다.

<template>
  <v-app ref="app">
    <v-app-bar></v-app-bar>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-toolbar-title>AppBar Title</v-toolbar-title>

      <v-btn icon>
        <v-icon>mdi-heart</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
    <v-main></v-main>
    <v-footer></v-footer>
  </v-app>
</template>

image

참고 사이트

  • https://next.vuetifyjs.com/en/components/app-bars/

Vuetify 기본 레이아웃(전체 레이아웃)

|

Vuetify 전체 레이아웃

기본적으로 Material Design의 레이아웃입니다.

image

  • v-app-bar
  • v-bottom-navigation
  • v-footer
  • v-navigation-drawer
  • v-system-bar
  • v-content
<template>
  <v-app ref="app">
    <v-navigation-drawer> </v-navigation-drawer>

    <v-app-bar> </v-app-bar>

    <v-main>
      <v-container fluid>
        <router-view></router-view>
      </v-container>
    </v-main>

    <v-footer> </v-footer>
  </v-app>
</template>

간단한 내용을 채운 예제

<template>
  <v-app>
    <v-navigation-drawer> </v-navigation-drawer>

    <v-app-bar color="primary">
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-toolbar-title>SnowDeer's Basic Layout</v-toolbar-title>
    </v-app-bar>

    <v-main class="pb-16">
      <v-container fluid>
        <h2>What is Lorem Ipsum?</h2>
        <div>
          Lorem Ipsum is simply dummy text of the printing and typesetting
          industry. Lorem Ipsum has been the industry's standard dummy text ever
          since the 1500s, when an unknown printer took a galley of type and
          scrambled it to make a type specimen book. It has survived not only
          five centuries, but also the leap into electronic typesetting,
          remaining essentially unchanged. It was popularised in the 1960s with
          the release of Letraset sheets containing Lorem Ipsum passages, and
          more recently with desktop publishing software like Aldus PageMaker
          including versions of Lorem Ipsum.
        </div>
        <br />
        <h2>Where does it come from?</h2>
        <div>
          Contrary to popular belief, Lorem Ipsum is not simply random text. It
          has roots in a piece of classical Latin literature from 45 BC, making
          it over 2000 years old. Richard McClintock, a Latin professor at
          Hampden-Sydney College in Virginia, looked up one of the more obscure
          Latin words, consectetur, from a Lorem Ipsum passage, and going
          through the cites of the word in classical literature, discovered the
          undoubtable source. Lorem Ipsum comes from sections 1.10.32 and
          1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and
          Evil) by Cicero, written in 45 BC. This book is a treatise on the
          theory of ethics, very popular during the Renaissance. The first line
          of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in
          section 1.10.32.
        </div>
        <br />
        <div>
          The standard chunk of Lorem Ipsum used since the 1500s is reproduced
          below for those interested. Sections 1.10.32 and 1.10.33 from "de
          Finibus Bonorum et Malorum" by Cicero are also reproduced in their
          exact original form, accompanied by English versions from the 1914
          translation by H. Rackham.
        </div>
        <br />
        <h2>Why do we use it?</h2>
        <div>
          It is a long established fact that a reader will be distracted by the
          readable content of a page when looking at its layout. The point of
          using Lorem Ipsum is that it has a more-or-less normal distribution of
          letters, as opposed to using 'Content here, content here', making it
          look like readable English. Many desktop publishing packages and web
          page editors now use Lorem Ipsum as their default model text, and a
          search for 'lorem ipsum' will uncover many web sites still in their
          infancy. Various versions have evolved over the years, sometimes by
          accident, sometimes on purpose (injected humour and the like).
        </div>
      </v-container>
    </v-main>
    <v-footer color="secondary" bottom fixed padless style="width: 100%">
      <div class="mx-auto">Copyright ©</div>
    </v-footer>
  </v-app>
</template>

참고 사이트

  • https://next.vuetifyjs.com/en/components/application/

Vue.js 3에서 Vuetify 사용하기

|

Vuetify

현재 Vuetify는 Vue 3를 지원하지 않습니다. 공식 페이지에서는 다음과 같이 2022년 5월 Vue 3를 지원하는 3.0이 릴리즈된다고 합니다.

The current version of Vuetify does not support Vue 3. Support for Vue 3 will come with the release of Vuetify v3. When creating a new project, please ensure you selected Vue 2 from the Vue CLI prompts, or that you are installing to an existing Vue 2 project.

따라서 현재는 Vue 3에서는 Vuetify 3 beta 버전을 이용해야 합니다. 물론 테스트 목적으로만 사용하고 공식적인 프로그램에서는 사용하지 말라고 경고하고 있습니다.

Vuetify 3 beta 버전 페이지는 여기입니다.


설치 방법

Vuetify를 설치하기 위해서는 아래 명령어를 이용합니다.

vue add vuetify

설치되고 나며, 자동으로 package.jsonmain.jsVuetify 관련 코드가 삽입됩니다.

main.js

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

loadFonts()

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

확인

확인을 위해 여기에서 간단한 예제를 App.vue에 삽입해보고 Vuetify가 잘 동작하는지 확인해봅니다.

App.vue

<template>
  <v-app ref="app">
    <v-app-bar color="grey-lighten-2" name="app-bar" class="justify-center">
      <div class="d-flex justify-center align-center w-100">
        <v-btn @click="print('app-bar')">Get data</v-btn>
      </div>
    </v-app-bar>
    <v-navigation-drawer color="grey-darken-2" permanent name="drawer">
      <div class="d-flex justify-center align-center h-100">
        <v-btn @click="print('drawer')">Get data</v-btn>
      </div>
    </v-navigation-drawer>
    <v-main>
      <v-card height="200px"></v-card>
    </v-main>
  </v-app>
</template>

<script>
export default {
  name: "App",
  data: () => ({
    layout: null,
  }),
  methods: {
    print(key) {
      alert(JSON.stringify(this.$refs.app.getLayoutItem(key), null, 2));
    },
  },
};
</script>

실행화면

image