Changing body styles in a vue router

I am using a Vue router with two pages:

let routes = [ { path: '/', component: require('./components/HomeView.vue') }, { path: '/intro', component: require('./components/IntroView.vue') } ] 

This works great, except that each of my components has different body styles:

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> 

My goal is for these two pages to have different background styles (eventually with a transition between them). But at the moment when I go to the home route (with a red background), then click on the intro route, the background color remains red (I want it to change to pink ).

Edit: 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> 
+12
source share
7 answers

I worked with the beforeCreate lifecycle hook and the global beforeCreate stylesheet. In global.css :

 body.home { background: red; } body.intro { background: pink; } 

In the <script> HomeView.vue :

 export default { beforeCreate: function() { document.body.className = 'home'; } } 

And it looks like IntroView.vue .

+25
source

Alternatively you can use this

It allows you to manage page body classes using vue-router. Wrote this when faced with a similar problem. Does it also refer to Add a class to the body when you click on a component?

+3
source

I ran into a problem when I wanted to change the styles of the html and body tags along with the #app container on certain routes, and found out that for various reasons it can be quite difficult.

After reading:

In your App.vue (can be considered as a centralized state):

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

Thus, for route / you get a red style, and for all other routes, a pink style is used.

handleStyles logic could be processed beforeCreated however in my case it will only affect the html and body styles but the #app element which displays the view of the router will only be available after mounting the dom, so I think this is a slightly more extensible solution.

+1
source
 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, } }, 

Another fairly simple solution, add it to the base App.vue file. To.name could be replaced with to.meta.class or similar for something more specific. It’s good to do it once, and it works forever.

+1
source

If the class is a specific view, maybe this will help

 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'); }, 

Move the methods section to the mixin, and then the code can be DRY.

0
source

You can also do this directly in the router file using the afterEach hook:

 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

to is a route object that contains the name of the route (if named), the path, etc. Documentation for all details

0
source

You can use the scoped attribute in the style element. Then the style will be limited only to this VUE file.

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
source

Source: https://habr.com/ru/post/1268839/


All Articles