강디너의 개발 일지

Vue - 동적 컴포넌트를 이용한 Layout 설정 본문

Javascript/Vue

Vue - 동적 컴포넌트를 이용한 Layout 설정

강디너 2020. 3. 24. 00:47
728x90
반응형

동적 컴포넌트란

컴포넌트를 동적 또는 비동기로 변경하고 싶을 때 v-bind:is를 사용하는 기능입니다.

이번 포스팅에서 보여드릴 예제는 router에서 특정 meta를 이용하여 레이아웃을 만들어보겠습니다.

 

프로젝트 기본 구성

짧게 설명드리자면 App 바로 아래 Layout을 둔 다음 slot으로 router-view를 둔 것입니다.

 

App.vue

<template>
  <div id="app">
      <the-layout>
        <router-view />
      </the-layout>
  </div>
</template>
<script>
import TheLayout from '@/layouts/TheLayout';

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

router/index.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home';
import MyPage from '../views/MyPage';
import Lounge from '../views/Lounge';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: { unauthorized: true },
  },
  {
    path: '/myPage',
    name: 'MyPage',
    component: MyPage,
  },
  {
    path: '/lounge',
    name: 'Lounge',
    component: Lounge,
    meta: { unauthorized: true, layout: 'MobileLayout' },
  },
]

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

export default router

 

부모 레이아웃에서는 자식 컴포넌트들, meta데이터를 받을 준비만 하면 됩니다.

저는 MobileLayout을 사용하는 컴포넌트에만 meta 태그를 준 후 없을 경우 DefaultLayout을 사용하도록 설계했습니다.

 

layouts/TheLayout.vue

<template>
    <component :is="layout" >
        <slot  />
    </component>
</template>

<script>
import { computed } from '@vue/composition-api';
import DefaultLayout from './DefaultLayout';
import MobileLayout from './MobileLayout';

export default {
    name: 'TheLayout',
    components: {
        DefaultLayout,
        MobileLayout,
    },
    setup(props, { root }){
        const layout = computed(() => root.$route.meta.layout || 'DefaultLayout' );

        return {
            layout,
        }
    }
}
</script>

 

layouts/DefaultLayout.vue

<template>
    <div>
        <the-header />
        <slot />
        <the-footer />
    </div>
</template>

<script>
import TheHeader from '../components/Menu/TheHeader';
import TheFooter from '@/components/Menu/TheFooter';

export default {
    name: 'DefaultLayout',
    components: {
        TheHeader,
        TheFooter,
    },
}
</script>

 

layouts/MobileLayout.vue

<template>
    <div>
        <slot></slot>
    </div>
</template>

<script>

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

 

 

DefaultLayout

 

MobileLayout

 

git : https://github.com/DinnerKang/study_vue/tree/7e4196a6961eb27df385b1e4672deaefae656474/deali-music

 

이해 안 되는 거 있으시면 댓글로 남겨주세요!!

 

 

ps. 저번 주말에 첫 후원이 들어와서 기분 좋게 글 씁니다!! ㅎㅅㅎ

커피한잔...
5 Comments
  • 프로필사진 자르르 2020.05.19 14:33 질문이 있습니다.
    TheLayout 부분에 setup에
    root.$route 부분에 $route를 경로를 읽어 드리질 못하는데, 혹시 다른데 이게 가능하게끔 설정하는 곳이 있나요?
  • 프로필사진 강디너 2020.05.20 12:15 신고 안녕하세요 ~!
    setup을 사용하신다는건 컴포지션 API를 사용하신다는거로 생각할게요 ~!
    혹시 root 를 로그 찍어서 확인해보실수 있으신가요 !? $route 라고 찾을 수 있습니다.
    vue-router가 설치 되었는지도 확인 부탁드릴게요 ~!
  • 프로필사진 강디너 2020.05.20 12:17 신고 $attrs: Object
    $children: [VueComponent]
    $createElement: ƒ (a, b, c, d)
    $el: div#app
    $listeners: (...)
    $options: {components: {…}, directives: {…}, filters: {…}, beforeCreate: Array(4), _base: ƒ, …}
    $parent: undefined
    $refs: {}
    $root: Vue {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
    $scopedSlots: {}
    $slots: {}
    $store: Store {_committing: false, _actions: {…}, _actionSubscribers: Array(0),

    ...

    $data: (...)
    $isServer: (...)
    $props: (...)
    $route: Object


    이런식으로 root 를 로그 찍으면 나옵니다 ~!
  • 프로필사진 임경민 2020.11.24 17:18 좋은 포스팅에 대해 감사합니다.
    한가지 궁금한점이 있어서 댓글을 적습니다.

    현재는 App 바로 아래 Layout에서 라우트를 meta에 따른 layout을 그렸는데

    App.vue 자체에서는 안되는건가요 ? 예를들어 App.vue lifeCycle에서 라우터 메타를 통해서 그려볼려고하는데

    라우터를 인지가 안되는거 같아서 글을 남겨봅니다. 이상입니다.
  • 프로필사진 강디너 2020.11.24 20:47 신고 router-view를 타고 라우터에 등록된 path, component, meta 등을 얻을수 있어서 맨 상위에있는 App.vue에서는 아무런 route 정보가 없는 것 같습니다.
댓글쓰기 폼