-
Notifications
You must be signed in to change notification settings - Fork 232
Layouts
Layouts are a great way to group page design or functionality in our app.
Our app.vue
is responsible for swapping out layouts depending on which layout is being used by a route. The app will look in the Vuex store for this.$store.state.common.layout
property and update the component reactively:
src/app.vue
<template lang="pug">
#app
component(:is="component")
slot
</template>
<script>
import PublicLayout from '@/layouts/public/main.vue'
import DefaultLayout from '@/layouts/default/main.vue'
export default {
name: 'App',
components: {
PublicLayout,
DefaultLayout
},
computed: {
component () {
return this.$store.state.common.layout
}
},
mounted () {
// Update page title.
this.$store.watch((state) => {
return state.common.title
}, (title) => {
document.title = title
console.log('title updated')
}, {
deep: true
})
}
}
</script>
A layout is associated with a route in the routes.js
file:
src/http/routes.js
/**
* Every route becomes a chunk, loaded only when used.
* Reduces size of initial App load.
*/
const routes = [
{
name: 'login',
path: '/login',
component: () => import(/* webpackChunkName: "login" */ '@/features/login/main.vue'),
title: 'Login',
layout: 'PublicLayout',
isPublic: true
},
{
name: 'home',
path: '/',
component: () => import(/* webpackChunkName: "dashboard" */ '@/features/dashboard/main.vue'),
title: 'Dashboard',
layout: 'DefaultLayout',
isPublic: false
},
// ...
]
export default routes
Functionality added to router.js
will change the Vuex store common.layout
property whenever a route is changed. Using a Vuex action store.dispatch('common/updateLayout', route.layout)
:
src/http/router.js
// ...
/**
* The Router instance containing all the routes for the application.
*/
const router = new Router({
base: '/app',
mode: 'history',
routes: routes.map(route => ({
name: route.name,
path: route.path,
component: route.component,
beforeEnter: (to, from, next) => {
// Setup some per-page stuff.
document.title = route.title
store.dispatch('common/updateTitle', route.title)
store.dispatch('common/updateLayout', route.layout)
// Auth navigation guard.
if (!route.isPublic) return guardRoute(to, from, next)
next()
}
}))
})
// ...
As an example, we have a default layout that we will use for most of our authenticated pages. The layout consists of a top app-toolbar, side-navigation drawer, footer, an app dialog and snackbar (for features in our app to use for basic messages if they so prefer):
src/layouts/default/main.vue
<template lang="pug">
v-app.my-default-layout
app-sidebar
app-bar
v-content(style="padding-top: 48px;")
transition(name="slide" mode="out-in")
router-view
app-footer
app-dialog
app-snackbar
</template>
<script>
import AppBar from '@/components/app-bar'
import AppSidebar from '@/components/app-sidebar'
import AppDialog from '@/components/app-dialog'
import AppSnackbar from '@/components/app-snackbar'
import AppFooter from '@/components/app-footer'
export default {
name: 'DefaultLayout',
components: { AppBar, AppSidebar, AppDialog, AppSnackbar, AppFooter },
methods: {
}
}
</script>
<style lang="stylus">
</style>
To demonstrate the swapping of one layout to another, we have a different layout we can use for an unauthenticated, public login page:
src/layouts/public/main.vue
<template lang="pug">
v-app
transition(name="slide" mode="out-in")
router-view
</template>
<script>
export default {
name: 'PublicLayout'
}
</script>
<style lang="stylus">
</style>