Reputation: 6973
I have a Vuex state property that stores a boolean that I use to determine whether to show or hide the nav bar. For all pages except the landing page the nav bar should appear so I set the default value to true.
export const state = () => ({
showNav: true
})
Then I have a mutation for toggling that.
export const mutations = {
toggleNav (state, show) {
state.showNav = show
}
}
In my landing page, I have a call to toggleNav
to turn off the nav bar.
export default {
mounted () {
this.$store.commit('toggleNav', false)
}
}
This works as expected with one big problem; When I refresh the landing page I see the nav bar for a brief second until mounted() gets called.
Is there some way to hide the nav bar such that it doesn't briefly appear? I realized I could default showNav
to false
and then call this.$store.commit('toggleNav', true)
on every page but that seems unwieldy.
EDIT: The nav bar is itself its own component.
EDIT 2: I forgot to add that I need to be able to dynamically show the nav bar when scrollY
exceeds a certain value and then hide it again when scrollY
returns below that value. My apologies to everyone who answered for not being clearer about this.
Upvotes: 3
Views: 1258
Reputation: 7080
In Nuxt, middlewares attached to a layout or a page are run on load and on every route change.
So the most straightforward way is to use a middleware to check for current path and toggle your nav:
/* store/index.js */
export const store = () => ({
showNav: true
});
export const mutations = {
toggleNav(state, bool){
state.showNav = bool;
}
}
/* middleware/toggleNavMiddleware.js */
export default function(context){
const { route, store } = context;
store.commit('toggleNav', route.path === /* your landing page path */);
}
/* layouts/default.vue (assuming this is the target) */
/* you can also use it in pages/*.vue */
export default {
middleware: ['toggleNavMiddleware'],
}
/* components/NavBar.vue */
<template>
<nav v-if="$store.state.showNav">
<!-- content here -->
</nav>
</template>
Upvotes: 1
Reputation: 9180
Rather than relying on state mutation, this had probably best be done during design-time by including a meta
field when defining the routes. Something like meta.showNavBar
. For example:
export default [
{
// The landing page
path: '/welcome',
name: 'Welcome',
meta: {
showNavbar: false
},
component: () => import('@/views/Welcome')
},
{
path: '/',
name: 'Homepage',
meta: {
// Don't worry about this since we'll take care of it with a computed property.
// showNavbar: true
},
component: () => import('@/views/Home')
},
{
// ...
}
]
<template>
<navbar v-if="showNavbar"></navbar>
</template>
<script>
export default {
computed: {
showNavbar() {
const { showNavbar } = this.$route.meta;
return showNavbar || typeof showNavbar === 'undefined';
}
}
}
</script>
Alternatively, you could call it meta.hideNavbar
, set it to true
for the landing page and coerce its value to boolean with double-negation operator (!!
) -- which will default to false
when not set or left undefined
, from here, you could simply do:
<navbar v-if="!!$route.meta.hideNavbar"></navbar>
Upvotes: 0