web-dev-qa-db-fra.com

Changer les styles de corps dans le routeur vue

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>
15
GluePear

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.

30
GluePear

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é?

3
Nikolay Antonov
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.

2
Lomax

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.

1
Craig van Tonder

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.

1
Syed

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

0
Loren

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>
0
Cazci_269