J'utilise Vue router avec deux pages:
let routes = [
{
path: '/',
component: require('./components/HomeView.vue')
},
{
path: '/intro',
component: require('./components/IntroView.vue')
}
]
Cela fonctionne bien, sauf que chacun de mes composants a un style de corps différent:
HomeView.vue:
<template>
<p>This is the home page!</p>
</template>
<script>
export default {
}
</script>
<style>
body {
background: red;
}
</style>
IntroView.vue:
<template>
<div>
<h1>Introduction</h1>
</div>
</template>
<script>
export default {
}
</script>
<style>
body {
background: pink;
}
</style>
Mon objectif est d'avoir ces deux pages avec des styles d'arrière-plan différents (éventuellement avec une transition entre elles). Mais au moment où je vais sur la route home
(avec le fond red
), puis cliquez sur la route intro
, la couleur de fond reste red
( Je veux qu'il change en pink
).
Modifier: index.html:
<body>
<div id="app">
<router-link to="/" exact>Home</router-link>
<router-link to="/intro">Introduction</router-link>
<router-view></router-view>
</div>
<script src="/dist/build.js"></script>
</body>
Je l'ai fait fonctionner avec le hook de cycle de viebeforeCreate
et une feuille de style globale. Dans global.css
:
body.home {
background: red;
}
body.intro {
background: pink;
}
Dans le <script>
section de HomeView.vue
:
export default {
beforeCreate: function() {
document.body.className = 'home';
}
}
Et similaire dans IntroView.vue
.
Vous pouvez également utiliser ceci
Il permet de contrôler vos classes de corps de page avec vue-router. A écrit cela face à un problème similaire. Il fait également référence à Ajouter une classe au corps lorsque le composant est cliqué?
watch: {
$route: {
handler (to, from) {
const body = document.getElementsByTagName('body')[0];
if (from !== undefined) {
body.classList.remove('page--' + from.name.toLowerCase());
}
body.classList.add('page--' + to.name.toLowerCase());
},
immediate: true,
}
},
Une autre solution assez simple, ajoutez-la à votre fichier App.vue de base. Le to.name peut être remplacé par to.meta.class ou similaire pour quelque chose de plus spécifique. C'est une bonne chose à faire une fois et cela fonctionne pour toujours une solution de type.
J'ai rencontré un problème lorsque je voulais modifier les styles des balises html
et body
avec les #app
conteneur sur des routes spécifiques et ce que j'ai découvert, c'est que pour diverses raisons, cela peut être assez compliqué.
Après avoir lu:
Dans votre App.vue (pourrait être considéré comme l'état centralisé):
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'my-app',
methods: {
handleStyles () {
// Red style to the body tag for the home page
if (['/'].includes(this.$route.path)) document.body.className = 'bg-red'
// Pink style to the body tag for all other pages
else if (document.body.classList.contains('bg-red')) document.body.className = 'bg-pink'
}
},
// Handle styles when the app is initially loaded
mounted () {
this.handleStyles()
},
// Handle styles when the route changes
watch: {
'$route' () {
this.handleStyles()
}
}
}
</script>
<style>
.bg-red {
background: red;
}
.bg-pink {
background: pink;
}
</style>
Donc pour l'itinéraire /
vous obtenez le style rouge et pour toutes les autres routes le style rose est appliqué.
La logique handleStyles
aurait pu être gérée par le crochet beforeCreated
mais dans mon cas, cela n'affecterait que les styles html
et body
mais le #app
l'élément dans lequel la vue du routeur est rendue ne serait disponible que lorsque le dom a été monté, donc je pense que c'est une solution légèrement plus extensible.
Si la classe est spécifique à la vue, cela peut aider
methods: {
toggleBodyClass(addRemoveClass, className) {
const el = document.body;
if (addRemoveClass === 'addClass') {
el.classList.add(className);
} else {
el.classList.remove(className);
}
},
},
mounted() {
this.toggleBodyClass('addClass', 'mb-0');
},
destroyed() {
this.toggleBodyClass('removeClass', 'mb-0');
},
Déplacez la section methods
vers un mixin, puis le code peut être SEC.
Vous pouvez également le faire directement dans le fichier du routeur en utilisant le hook afterEach
:
mainRouter.afterEach((to) => {
if (["dialogs", "snippets"].includes(to.name)) {
document.body.style.backgroundColor = "#F7F7F7";
// or document.body.classList.add(className);
} else {
document.body.style.backgroundColor = "#FFFFFF";
// or document.body.classList.remove(className);
}
});
afterEach
documentation de hook
to
est un objet route qui contient le nom de la route (s'il est nommé), le chemin, etc. Documentation pour tous les accessoires
Vous pouvez utiliser un attribut de portée dans l'élément de style. Ensuite, le style sera limité uniquement à ce fichier vue.
HomeView.vue:
<template>
<p>This is the home page!</p>
</template>
<script>
export default {
}
</script>
<style scoped>
body {
background: red;
}
</style>
IntroView.vue:
<template>
<div>
<h1>Introduction</h1>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
body {
background: pink;
}
</style>