Vue.js 3.0 기본 레이아웃 - (2) AppBar 레이아웃

|

AppBar 레이아웃

<template>
  <div id="wrapper">
    <div id="drawer"></div>
    <div id="main">
      <div id="appbar">
        <div id="hamburg-menu" class="h-center v-center">
          <i class="bi bi-list"></i>
        </div>
        <div id="title" class="v-center">AppBar Title</div>
        <div id="action-items">
          <i class="action-item bi bi-heart"></i>
          <i class="action-item bi bi-three-dots-vertical"></i>
        </div>
      </div>
      <div id="content"></div>
    </div>
  </div>
</template>

<style>
.h-center {
  display: flex;
  flex-direction: row;
  justify-content: center;
}

.v-center {
  display: flex;
  flex-direction: row;
  align-items: center;
}

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

#wrapper {
  display: -webkit-flex;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  width: 100vw;
  height: 100vh;
  margin: 0 auto;
}

#appbar {
  display: flex;
  flex-direction: row;
  height: 48px;
  background: #edb1f1;
}

#hamburg-menu {
  width: 48px;
  height: 48px;
  background: #d59bf6;
  cursor: pointer;
}

#title {
  flex: 1;
  height: 48px;
}

#action-items {
  display: flex;
  flex-direction: row;
  height: 48px;
  background: #d59bf6;
}

.action-item {
  width: 48px;
  height: 48px;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}

#drawer {
  width: 200px;
  height: 100vh;
  background: #5585b5;
}

#main {
  flex: 1;
  flex-flow: column wrap;
  justify-content: flex-start;
  background: #bbe4e9;
}
</style>

image

Vue.js 3.0 기본 레이아웃 - (1) 스켈레톤 레이아웃

|

기본 스켈레톤 레이아웃

<template>
  <div id="wrapper">
    <div id="drawer"></div>
    <div id="main">
      <div id="appbar"></div>
      <div id="content"></div>
    </div>
  </div>
</template>

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

#wrapper {
  display: -webkit-flex;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  width: 100vw;
  height: 100vh;
  margin: 0 auto;
}

#drawer {
  width: 200px;
  height: 100vh;
  background: #5585b5;
}

#main {
  flex: 1;
  flex-flow: column wrap;
  justify-content: flex-start;
  background: #bbe4e9;
}

#appbar {
  height: 48px;
  background: #53a8b6;
}
</style>

image

Vue.js 3.0 기본 여백(margin) 제거하기

|

Vue 기본 여백(margin) 제거하기

Vue.js로 화면을 띄우면 기본적으로 상하좌우 8px의 여백이 있습니다. 아래의 코드를 이용해서 여백을 없앨 수 있습니다.

위치는 App.vue에 넣어도 되고, public/index.html에 넣어도 되는데 후자가 더 깔끔한 위치라고 생각합니다.

<style>
body {
  margin: 0px;
}
</style>

Vue.js 3.0 Event 상위로 전달하는 방법(Emit)

|

Emit 사용 방법

emit는 컴포넌트에서 발생한 이벤트를 상위 부모에게 전달하는 키워드입니다. 다음과 같이 script 코드에서 이벤트를 발생하는 방법과 template 코드에서 이벤트를 발생시키는 2가지 방법이 있습니다.

emit 예제

<template>
  <h2>Child Component</h2>

  <button @click="onClicked">Emit from script</button>
  <button @click="$emit('event2', 2)">Emit from template</button>
</template>

<script>
export default {
  emits: ["event1", "event2"],
  setup(props, context) {
    const { emit } = context;
    const onClicked = () => {
      emit("event1", 10);
    };

    return {
      onClicked,
    };
  },
};
</script>

getCurrentInstance 사용

emitgetCurrentInstance()를 이용해서도 획득할 수 있었습니다. 기존에는 useContext를 이용해서 획득할 수 있었는데, Vue 3.2.0 버전부터 useContextdeprecated 되었습니다.

import { getCurrentInstance } from "vue";

export default {
  emits: ["event1", "event2"],
  setup() {
    const { emit } = getCurrentInstance();
    const onClicked = () => {
      emit("event1", 10);
    };

    return {
      onClicked,
    };
  },
};

<script setup> 내에서 사용하는 방법

<script setup>
import { defineEmits } from "vue";

const emit = defineEmits(["toggle-drawer"]);
const toggleDrawer = () => {
  emit("toggle-drawer");
};
</script>

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>