Ben Carey
Ben Carey

Reputation: 16958

Page (router view) dependant header style in Vue.js

A little background...

This may seem like a basic issue, or something that could be easily solved with $emit, however, I think events may be a bit overkill for what I am trying to achieve, and as such, would like to see if anyone has an alternative, either by design, or by something I am not aware of in Vue...

Consider the following structure:

App.vue

<template>

    <div id="app">

        <!-- Include the main site header -->
        <main-header></main-header>

        <!-- Include the content of the current page -->
        <router-view></router-view>

    </div>

</template>

<script>

    import Header from 'core-js/components/core/Header';

    export default {

        components: {
            'main-header': Header
        }

    }

</script>

SomePage.vue - router view content

<template>

    <main id="main-content" role="main">

        <!-- All the page content here... -->

    </main>

</template>

<script>

    export default {

        // Set the component properties here...

    }

</script>

What am I actually trying to achieve!?

Notice that the main-header component is a sibling to the router-view component... Very simply, I would like to add a class to the main-header component based on the content of the router-view.

For example, let's say that SomePage.vue has dark content, we will want to add the light class to the main-header component.

I appreciate this could be fixed in a matter of seconds with $emit, but I am hesitant to use events on something so basic.

In short, can anyone suggest an alternative solution to Vue events, or a better design structure?

Additional Information

Just to make it clear what I am trying to achieve, see the following App.vue template:

<template>

    <div id="app">

        <!-- Include the main site header -->
        <main-header :class="{ light: lightHeader }"></main-header>

        <!-- Include the content of the current page -->
        <router-view></router-view>

    </div>

</template>

<script>

    import Header from 'core-js/components/core/Header';

    export default {

        components: {
            'main-header': Header
        },

        data() {
            return {
                lightHeader: false
            }
        }

    }

</script>

Then, SomePage.vue would somehow set lightHeader to true...

Upvotes: 2

Views: 2739

Answers (1)

Nick G
Nick G

Reputation: 1973

You could consider adding a meta field to each route in router.ts, like so:

routes: [{
    name: 'header',
    component: Header,
    meta: {
        headerClass: 'light'
   }
}]

Then you would use it in your template like:

<template>    
    <div id="app">    
        <main-header :class="$route.meta.headerClass"></main-header>
        <router-view></router-view>    
    </div>    
</template>

See the example I made here: https://jsfiddle.net/wugq6typ/

Upvotes: 2

Related Questions