使用 Vue.js 体验导航栏闪烁

Experiencing navbar flicker with Vue.js

在函数被评估为 true 或 false 之前,我的导航栏出现闪烁。

需要评估的函数如下:

export default {
  methods: {
    isAuthenticated () {
      return this.$store.state.user.authenticated
    }
  },
  data: () => {
    return {
      unauthenticated: [
        {
          title: 'Link1',
          url: '/link1'
        },
        {
          title: 'Link2',
          url: '/link2'
        },
        {
          title: 'Link3',
          url: '/link3'
        }
      ],
      authenticated: [
        {
          title: 'otherLink1',
          url: '/otherlink1'
        },
        {
          title: 'otherLink2',
          url: '/otherlink2'
        },
        {
          title: 'otherLink3',
          url: '/otherlink3'
        }
      ]
    }
  }
}

导航栏有以下内容:

<template v-if="isAuthenticated()">
  <b-nav is-nav-bar>
    <b-nav-item v-for="nav in authenticated" :key="nav.title" :href="nav.url">{{nav.title}}</b-nav-item>
  </b-nav>
</template>
<template v-else>
  <b-nav is-nav-bar>
    <b-nav-item v-for="nav in unauthenticated" :key="nav.title" :href="nav.url">{{nav.title}}</b-nav-item>
  </b-nav>
</template>

但是,当我点击导航时,未经身份验证的链接出现一秒钟,然后经过身份验证的链接出现,就好像 isAuthenticated() 函数尚未计算一样。我该怎么做才能消除这种闪烁?

我的商店文件 (user.js) 文件如下所示:

export const state = () => ({
  headers: {},
  profile: {}
})

export const mutations = {
  updateHeaders (state, headers) {
    state.headers.access_token = headers['access-token']
    state.headers.token_type = headers['token-type']
    state.headers.client = headers['client']
    state.headers.expiry = headers['expiry']
    state.headers.uid = headers['uid']
    if (state.headers.expiry == null) {
      state.authenticated = false
    } else {
      let timeToExpiry = new Date(state.headers.expiry * 1000)
      let now = new Date()
      state.authenticated = now < timeToExpiry
    }
  },
  signout (state) {
    state.headers = {}
    state.profile = {}
  }
}

login/logout 方法通过 API 调用 Rails 应用程序实现。 Devise gem 处理剩下的事情。

提前致谢!

编辑:

我将 Nuxt.js 用于 layouts/pages/components,因此我相信链接在后台提交时带有 this.$router.push(url)

b-nav 标签来自 Bootstrap Vue

没有说明单击其中一个链接时执行的代码,我假设它类似于 this.$router.push(url)。如果是这种情况,您可能已将导航栏包含在 <router-view> 中,因此当您切换当前路线时,<router-view> 内的组件会重新呈现,因此导航栏会闪烁。将它们移出 <router-view> 应该可以解决这个问题。

编辑:所以OP还没有使用vue-router,在这种情况下,要么手动更改根组件的数据以使导航以外的部分发生变化,或添加 vue-router 并使用 this.$router.push() 导航,这样 <router-view> 之外的部分就不会改变或闪烁。

无论如何,我们需要 vue 组件留下来让 vue 只重新渲染视图的一部分,而简单地通过 <a> 导航或其他东西会破坏所有东西并再次重建它们,因此闪烁。

使用 bootstrap-vue 时,有两种方法可以将 link 添加到导航栏。一种是绑定到 :href 属性,这会创建一个常规的 html 锚点。另一种是使用:to属性,它创建一个与vue-router交互的link。

<b-navbar-nav v-if="isAuthenticated()">
    <b-nav-item v-for="nav in authenticated" :key="nav.title" :to="nav.url">{{nav.title}}</b-nav-item>
</b-navbar-nav>
<b-navbar-nav v-if="!isAuthenticated()">
    <b-nav-item v-for="nav in unauthenticated" :key="nav.title" :to="nav.url">{{nav.title}}</b-nav-item>
</b-navbar-nav>

没有理由在这里使用 <template> 标签来封装 .另请注意 'is-nav-bar' 已弃用。请参阅 here 他们指出弃用的地方。