Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue Dynamic Layouts mounting router-view component twice

I setup my Vue project to use dynamic layouts - that is, layouts that persist from page to page, assuming the layout for the new page is the same as the last page. My problem is that when I go to a route with a different layout, the router-link component gets created and destroyed, then created again, which is causing me some issues. My setup is as follows:

App.vue

<template>
  <component :is="layout">
    <router-view :layout.sync="layout" />
  </component>
</template>

<script>
import LayoutPortal from '@/layouts/LayoutPortal';
import LayoutOffline from '@/layouts/LayoutOffline';
import LayoutDefault from '@/layouts/LayoutDefault';

export default {
  name: 'App',

  components: {
    LayoutPortal,
    LayoutOffline,
    LayoutDefault,
  },
...

Some router-view Component

<template>
...
</template>

<script>
import LayoutDefault from '@/layouts/LayoutDefault';

export default {
    ...

    created() {
        this.$emit('update:layout', LayoutDefault);
    },
}
</script>

Layout Default

<template>
  <div class="wrapper">
    <slot />
  </div>
</template>

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

tldr;

If you setup your project using dynamic layouts, following any of a number of tutorials out there online, when you navigate to a route with a different layout than the last page, the new router-view component gets created, destroyed, then created again. This causes issues like doubling up on mounted() calls and more.

like image 430
Ryan Bobrowski Avatar asked Nov 17 '22 14:11

Ryan Bobrowski


1 Answers

I ultimately went with nested (child) routes (https://router.vuejs.org/guide/essentials/nested-routes.html):

{
      path: '/portal',
      component: LayoutPortal,
      beforeEnter(to, from, next) {
        if (!store.getters.auth) {
          next('/login');
          return;
        }

        next();
      },
      children: [
        {
          path: 'home',
          name: 'portal-home',
          component: PortalHome,
        },
        {
          path: 'about',
          name: 'portal-about',
          component: PortalAbout,
        },
        ...

In this way I can load up the layout as the parent route, separate beforeEnter logic into separate route groups, and avoid the problem where going to a page with a new layout loads a component twice.

like image 189
Ryan Bobrowski Avatar answered Dec 04 '22 08:12

Ryan Bobrowski