On my application I have multiple layouts. They are separated in different folders. I would like to use different SCSS files for the layouts. However no matter what layout is in use (based on a prop on router meta), all the SCSS files are imported. This messes up the layouts because the styles got mixed. Is there a way of import only the SCSS related to the layout on use?
App.vue
<template>
<component :is="layout" />
</template>
<script>
import DefaultLayout from '@/layouts/default/DefaultLayout';
import PrimaryLayout from '@/layouts/primary/PrimaryLayout';
import SecondaryLayout from '@/layouts/secondary/SecondaryLayout';
export default {
components: {
DefaultLayout,
PrimaryLayout,
SecondaryLayout
},
data() {
return {
layout: null
}
},
watch: {
$route(to, from) {
document.title = to.meta.title;
this.layout = to.meta.layout || 'DefaultLayout';
}
}
};
</script>
src/layouts/primary/PrimaryLayout.vue
<template>
Html content here
<router-view />
</template>
<script>
export default {
name: 'PrimaryLayout'
}
</script>
<style lang="scss">
@import '@/assets/layouts/primary/scss/main.scss';
</style>
src/layouts/secondary/SecondaryLayout.vue
<template>
Different html content here
<router-view />
</template>
<script>
export default {
name: 'SecondaryLayout'
}
</script>
<style lang="scss">
@import '@/assets/layouts/secondary/scss/main.scss';
</style>
src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/pages/auth/Login.vue'),
meta: {
layout: 'PrimaryLayout',
title: 'Auth Page'
}
},
{
path: '/admin',
name: 'Admin',
component: () => import('@/pages/admin/Admin.vue'),
children: [
{
path: '',
name: 'Dashboard',
component: () => import('@/pages/admin/Dashboard.vue'),
meta: {
layout: 'SecondaryLayout',
title: 'Admin | Home'
},
},
... other pages ...
]
}
]
Can aynone give me a help?
If the application has been generated using Vue CLI and uses Webpack under the hood, we can rely on Webpack's code splitting functionality by switching to dynamic imports:
So instead of
<script>
import DefaultLayout from '@/layouts/default/DefaultLayout';
import PrimaryLayout from '@/layouts/primary/PrimaryLayout';
import SecondaryLayout from '@/layouts/secondary/SecondaryLayout';
export default {
components: {
DefaultLayout,
PrimaryLayout,
SecondaryLayout
},
...
};
</script>
we import layout components like this:
<script>
export default {
components: {
DefaultLayout: () => import('@/layouts/default/DefaultLayout'),
PrimaryLayout: () => import('@/layouts/primary/PrimaryLayout'),
SecondaryLayout: () => import('@/layouts/secondary/SecondaryLayout')
},
...
};
</script>
This should instruct Webpack and Vue Loader to put code for those components into separate bundles and only load the ones which are currently necessary.
Users navigating from route with Layout A to the route with Layout B will end up with styles for both layouts loaded and applied. To guarantee true isolation is it better to use scoped or module styles.
Another (and in my opinion a better) way of assigning layouts to different pages is to use slots.
This will result in a more concise code as there will be no need to declare meta properties for the routes and to watch them in App.vue. Code splitting would also work OOTB in the given case, as webpack dynamic imports are already used for view components in the router.
<template>
<router-view></router-view>
</template>
<template>
... Layout-specific HTML here
<slot></slot>
... more layout-specific HTML
</template>
<template>
<PrimaryLayout>
... Login.vue component template goes here
</PrimaryLayout>
</template>
<script>
import PrimaryLayout from '@/layouts/primary/PrimaryLayout';
export default {
components: { PrimaryLayout }
}
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With