【问题标题】:Conditional state based on the route基于路由的条件状态
【发布时间】:2020-01-12 17:53:53
【问题描述】:

我有一个 Vuex 状态属性,它存储一个布尔值,我用它来确定是显示还是隐藏导航栏。对于除登录页面之外的所有页面,导航栏都应该出现,因此我将默认值设置为 true。

export const state = () => ({
    showNav: true
})

然后我有一个用于切换的突变。

export const mutations = {
    toggleNav (state, show) {
        state.showNav = show
    }
}

在我的登录页面中,我致电toggleNav 以关闭导航栏。

export default {
    mounted () {
        this.$store.commit('toggleNav', false)
    }
}

这符合预期,但有一个大问题;当我刷新登录页面时,我会看到导航栏一小会儿,直到 mount() 被调用。

有什么方法可以隐藏导航栏,使其不会短暂出现吗?我意识到我可以默认 showNavfalse,然后在每个页面上调用 this.$store.commit('toggleNav', true),但这似乎很笨拙。

编辑:导航栏本身就是它自己的组件。

编辑2:我忘了补充一点,我需要能够在scrollY 超过某个值时动态显示导航栏,然后在scrollY 返回低于该值时再次隐藏它。我向所有回答的人道歉,因为没有更清楚地说明这一点。

【问题讨论】:

  • 尝试使用 created 钩子,因为它在生命周期的早期......或者如果您使用 vue-router,则可能是重新使用的 navigation guard(在 @987654332 内提交@守卫)。
  • @zer0kompression 这些都不起作用。我认为这些在生命周期中仍然发生得太晚了。
  • 根据当前路由在导航栏组件上使用v-if怎么样?所以像<navbar v-if="$route.path !== '/landing-page-path'"/>.
  • @zer0kompression 查看我的第二次编辑。实际上,我确实曾经有过v-if="$route.path !== '/landing-page-path'",但在页面加载后我无法让导航栏再次动态显示。

标签: vue.js vuex nuxt.js


【解决方案1】:

在 Nuxt 中,附加到布局或页面的中间件运行 on load and on every route change

所以最直接的方法是使用中间件来检查当前路径并切换您的导航:

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

【讨论】:

  • @DarrellBrogdon 我自己测试过,效果很好。所以请展示/解释更多你的代码,或者让我知道你是如何实现它的?。
  • export default function 有语法错误(不必要的尾括号),如果我错了,请纠正我,但 $store.state.showNav 应该引用 toggleNav 而不是 showNav,不是吗?我应该澄清的是,如果我解决了这些问题,那么导航栏确实会消失,但是(这是我的错,因为我的问题没有明确)我无法在页面加载后动态显示导航栏。实际上,当用户滚动到页面顶部并再次出现导航时,我需要调用store.commit('toggleNav', true)
  • @DarrellBrogdon 更正了尾随括号。根据您的 sn-p,它应该引用 $store.state.showNav,因为这是在 state = () =&gt; ({ showNav: true }) 中公开的内容。 toggleNav 处于突变状态,因此不应作为参考,只能提交。您可以更新您的问题以使其更清楚吗?澄清一下,导航栏应该在加载时消失,但如果用户滚动到顶部,导航栏会再次出现,对吗?
  • 是的,感谢您的澄清。实施后,它确实按预期工作。
  • @DarrellBrogdon 很高兴它有帮助。
【解决方案2】:

与其依赖状态突变,最好在设计时通过在定义路由时包含meta 字段来完成。像meta.showNavBar 这样的东西。例如:

routes.js

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

  {
    // ...
  }
]

SomeComponent.vue

<template>
  <navbar v-if="showNavbar"></navbar>
</template>

<script>
  export default {
    computed: {
      showNavbar() {
        const { showNavbar } = this.$route.meta;

        return showNavbar || typeof showNavbar === 'undefined';
      }
    }
  }
</script>

或者,您可以将其命名为meta.hideNavbar,将其设置为true 用于登录页面,并使用双重否定运算符 (!!) 将其值强制为布尔值,否则默认为 false设置或离开undefined,从这里,你可以简单地做:

<navbar v-if="!!$route.meta.hideNavbar"></navbar>

【讨论】:

  • 这不起作用。我猜是因为我使用的是 NuxtJS 而不是纯 Vue?
  • 基本思想可以用中间件组件(Nuxt)来实现
  • @DarrellBrogdon 不太清楚它与 NuxtJs 版本有何不同,但是是的,这个最小的设置通常对我来说就足够了。我自己不使用 NuxtJs,所以。不过很高兴你找到了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-04
  • 2019-05-12
  • 2019-04-08
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多