L'utilisation des routes, et en particulier des routes enfants, est une excellente façon d'aborder les mises en page communes dans Vue.
Tout ce code utilise Vue 2.x
Commencez par avoir un composant vue très simple appelé App qui n'a pas de mise en page.
app.vue
<template>
<router-view></router-view>
</template>
Créez ensuite un fichier Routes que vous introduirez dans votre instance Vue.
Routes.(ts|js)
import Vue from 'vue'
import VueRouter from 'vue-router'
const NotFoundComponent = () => import('./components/global/notfound.vue')
const Login = () => import('./components/account/login.vue')
const Catalog = () => import('./components/catalog/catalog.vue')
export default new VueRouter({
mode: 'history',
linkActiveClass: 'is-active',
routes: [
//Account
{ path: '/account', component: () => import('./components/account/layout.vue'),
children: [
{ path: '', component: Login },
{ path: 'login', component: Login, alias: '/login' },
{ path: 'logout',
beforeEnter (to: any, from: any, next: any) {
//do logout logic
next('/');
}
},
{ path: 'register', component: () => import('./components/account/register.vue') }
]
},
//Catalog (last because want NotFound to use catalog's layout)
{ path: '/', component: () => import('./components/catalog/layout.vue'),
children: [
{ path: '', component: Catalog },
{ path: 'catalog', component: Catalog },
{ path: 'category/:id', component: () => import('./components/catalog/category.vue') },
{ path: 'product', component: () => import('./components/catalog/product.vue') },
{ path: 'search', component: () => import(`./components/catalog/search.vue`)} ,
{ path: 'basket', component: () => import(`./components/catalog/basket.vue`)} ,
{ path: '*', component: NotFoundComponent }
]
}
]
})
Le code utilise le lazy loading (avec webpack), donc ne laissez pas l'option () => import(...)
vous lancer. Il aurait pu s'agir d'un simple import(...)
si vous souhaitez un chargement rapide.
L'important, ce sont les itinéraires des enfants. Nous définissons donc le chemin principal de /account
d'utiliser le /components/account/layout.vue
mais les deux premiers enfants spécifient la vue du contenu principal (Login). J'ai choisi de procéder de cette manière parce que si quelqu'un navigue simplement vers /account, je veux l'accueillir avec l'écran de connexion. Il peut être approprié pour votre application que /account soit une page d'atterrissage où ils peuvent vérifier l'historique des commandes, changer les mots de passe, etc...
J'ai fait la même chose pour le catalogue... /
y /catalog
tous deux chargent le catalog/layout
avec le /catalog/catalog
fichier.
Notez également que si vous n'aimez pas l'idée d'avoir des "sous-dossiers" (c'est-à-dire account/login au lieu de /login), vous pouvez avoir des alias comme je le montre dans le login.
En ajoutant , alias: '/login'
cela signifie que les utilisateurs peuvent naviguer vers /login
même si l'itinéraire réel est /account/login
.
C'est la clé du problème, mais pour essayer de compléter l'exemple...
Voici mon fichier de démarrage qui relie mon app.vue et mes routes :
boot.(ts|js)
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import App from './components/app.vue';
import router from './routes';
new Vue({
el: '#app',
router,
render: h => h(App)
});
J'ai créé un fichier layout.vue pour chacune des sections principales de mon application (compte, catalogue, etc.).
account/layout.vue
<template>
<div>
<cc-header></cc-header>
<div class="container">
<main>
<router-view></router-view>
</main>
<aside>
</aside>
</div>
<cc-footer></cc-footer>
</div>
</template>
<script lang="ts">
import ccHeader from "../common/cc-header.vue"
import ccFooter from "../common/cc-footer.vue"
export default {
components: {
ccHeader,
ccFooter
}
}
</script>
<style lang="scss" scoped>
.container {
display: flex;
}
main {
flex: 3;
order: 2;
}
aside {
flex: 1;
order: 1;
}
</style>
Et la mise en page du catalogue...
catalog/layout.vue
<template>
<div>
<cc-header></cc-header>
<div class="catalog-container">
<main class="catalog">
<router-view></router-view>
</main>
<cc-categories></cc-categories>
</div>
<cc-footer></cc-footer>
</div>
</template>
<script lang="ts">
import ccHeader from "../common/cc-header.vue"
import ccFooter from "../common/cc-footer.vue"
import ccCategories from "./cc-categories.vue"
export default {
components: {
ccCategories,
ccHeader,
ccFooter
},
data : function() : any {
return {
search: ''
}
},
}
</script>
<style lang="scss" scoped>
.catalog-container {
display: flex;
}
.category-nav {
flex: 1;
order: 1;
}
.catalog {
flex: 3;
order: 2;
}
</style>
Les deux présentations utilisent des composants communs tels que l'en-tête et le pied de page, mais ce n'est pas nécessaire. La présentation du catalogue comporte des catégories dans la barre de navigation latérale, alors que la présentation du compte n'en comporte pas. Je place mes composants communs sous components/common.
common/footer.vue
<template>
<div>
<hr />
<footer>
<div class="footer-copyright">
<div>© Copyright {{year}} GlobalCove Technologies, LLC</div>
<div>All rights reserved. Powered by CoveCommerce.</div>
</div>
</footer>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.component('cc-footer', {
data : function() : any {
return {
year: new Date().getFullYear()
}
},
})
</script>
<style lang="scss">
</style>
Structure générale du fichier
src/
boot.ts
routes.ts
components/
app.vue
catalog/
layout.vue
catalog.vue
category.vue
product.vue
search.vue
basket.vue
account/
layout.vue
login.vue
register.vue
global/
notfound.vue
common/
cc-header.vue
cc-footer.vue
La combinaison des routes, d'un app.vue simple, de fichiers de mise en page spécifiques et de composants communs devrait vous permettre d'atteindre vos objectifs.
0 votes
Pour les curieux, voici un lien avec des options intéressantes pour gérer les mises en page avec
vue
: markus.oberlehner.net/blog/dynamic-vue-layout-components0 votes
Une bonne solution est : levelup.gitconnected.com/