简体   繁体   English

Vue.js:无论用户是否登录,导航栏上的显示/隐藏按钮均基于Vuex商店状态

[英]Vue.js: Show/Hide buttons on navbar based on Vuex Store state when the user is logged in or not

I'm creating a navbar that shows or hides buttons depending if the user is logged in or not. 我正在创建一个导航栏,该导航栏显示或隐藏按钮,具体取决于用户是否登录。 For that, I'm saving the state on Vuex and localStorage. 为此,我将状态保存在Vuex和localStorage上。

I'm trying to build a dynamic menu, using a list of objects (ie rightMenu ) that contains the information of the buttons (ie route, title and a flag that indicates if the button may show or not if the user is logged in). 我正在尝试使用包含按钮信息的对象列表(即rightMenu )来构建动态菜单(即,路线,标题和一个标志,该标志指示用户登录时按钮是否可以显示) 。

Always that the user logs in the system, the this.$store.state.auth.isUserLoggedIn changes to true , however the template does not change, the button stays in the same initial state when the user was not logged in. For example: the sign out button does not show when this.$store.state.auth.isUserLoggedIn updates. 始终使用户登录系统, this.$store.state.auth.isUserLoggedIn更改为true ,但是模板未更改,当用户未登录时按钮保持在相同的初始状态。例如: this.$store.state.auth.isUserLoggedIn更新时, sign out按钮不显示。 But when I click 'ctrl+F5' and the page reloads, the buttons show correctly. 但是,当我单击“ Ctrl + F5”并重新加载页面时,按钮会正确显示。 In this case, for example, the sign out button appears correctly when I reload the page manually. 例如,在这种情况下,当我手动重新加载页面时, sign out按钮会正确显示。

I'm thinking in to force the page to reload again when the user logs in or logs out, however I believe that it is not a good option. 我正在考虑强迫用户登录或注销时再次重新加载页面,但是我认为这不是一个好选择。

Could anyone help me? 有人可以帮我吗?

I'm giving the code that I'm using below. 我在下面提供我正在使用的代码。

Thank you in advance. 先感谢您。

Menu.vue > template Menu.vue>模板

<div>
    <v-toolbar color='grey darken-3' dark>
        <v-toolbar-title>Site</v-toolbar-title>

        ...

        <v-toolbar-items class='hidden-sm-and-down'>
            <v-btn v-for='item in rightMenu' :key='item.title'
                   :to='item.to' v-if='item.showButton' flat>
                   {{ item.title }}
            </v-btn>
        </v-toolbar-items>

    </v-toolbar>

    <router-view/>
</div>

Menu.vue > script Menu.vue>脚本

export default {
  data () {
    return {
      rightMenu: [
        { to: '/sign_in', title: 'sign in'
          showButton: !this.$store.state.auth.isUserLoggedIn },
        { to: '/sign_up', title: 'sign up'
          showButton: !this.$store.state.auth.isUserLoggedIn },
        { to: '/sign_out', title: 'sign out'
          showButton: this.$store.state.auth.isUserLoggedIn }
      ]
    }
  },
  ...
}

store.js store.js

const store = new Vuex.Store({
  state: {
    auth: {
      token: '',
      isUserLoggedIn: false
    }
  },
  mutations: {
    setAuthToken (state, token) {  // I use it on the Login
      state.auth.token = token
      state.auth.isUserLoggedIn = !!token
      localStorage.setItem('store', JSON.stringify(state))
    },
    cleanAuth (state) {  // I use it on the Logout
      state.auth = {
        token: '',
        isUserLoggedIn: false
      }
      localStorage.setItem('store', JSON.stringify(state))
    }
  }
  ...
})

EDIT 1: 编辑1:

When I use this.$store.state.auth.isUserLoggedIn explicitly on my code, it works well. 当我在代码上显式使用this.$store.state.auth.isUserLoggedIn ,它可以很好地工作。 So, the button appears and disappears correctly. 因此,该按钮出现并正确消失。 I give below an example: 我在下面举一个例子:

Menu.vue > template Menu.vue>模板

<v-toolbar-items class='hidden-sm-and-down'>
    <v-btn v-if='this.$store.state.auth.isUserLoggedIn' flat> 
      Test {{ this.$store.state.auth.isUserLoggedIn }}
    </v-btn>
</v-toolbar-items>

Hence, I believe that the problem is in the binding of showButton with this.$store.state.auth.isUserLoggedIn . 因此,我相信问题在于showButtonthis.$store.state.auth.isUserLoggedIn

Use computed property to make it reactive : 使用computed属性使其具有reactive

 <template> ... <v-btn v-for='item in rightMenu' :key='item.title' :to='item.to' v-if='isUserLoggedIn(item.title)' flat> {{ item.title }} </v-btn> ... </template> <script> ... computed: { isUserLoggedIn() { return (title) => { // you'll not have any caching benefits if (title === 'sign out') { return this.$store.state.auth.isUserLoggedIn; } return !this.$store.state.auth.isUserLoggedIn; } } } ... </script> 

Through the answers of Chris Li, Andrei Gheorghiu and Sajib Khan I could solve my problem. 通过Chris Li,Andrei Gheorghiu和Sajib Khan的回答,我可以解决我的问题。

Andrei Gheorghiu have explained that I can't access computed properties in data() and Chris Li suggested that I use a computed variable instead. Andrei Gheorghiu解释说我无法访问data()计算属性,而Chris Li建议我改用计算变量。 These answers plus Sajib Khan example I was able to think in a solution that I share below. 这些答案以及萨吉布·汗(Sajib Khan)的例子让我得以思考,下面我将分享一个解决方案。 I hope that it help others in the future. 希望以后对其他人有帮助。

In a nutshell, I've created a computed property that returns my array and always when this.$store.state.auth.isUserLoggedIn updates, the array changes together (consequently the menu as well). 简而言之,我创建了一个计算属性,该属性返回我的数组,并且总是在this.$store.state.auth.isUserLoggedIn更新时,数组一起更改(因此也更改了菜单)。

I intent to create a mapGetter to my this.$store.state.auth.isUserLoggedIn . 我打算为我的this.$store.state.auth.isUserLoggedIn创建一个this.$store.state.auth.isUserLoggedIn As soon as I do it, I update the answer. 一旦完成,我就会更新答案。

Thank you guys so much. 谢谢你们

<script>
export default {
  data () {
    return { ... }
  },
  computed: {
    rightMenu () {
      return [
        { title: 'sign_in', to: '/sign_in', 
            showButton: !this.$store.state.auth.isUserLoggedIn },
        { title: 'sign_up', to: '/sign_up', 
            showButton: !this.$store.state.auth.isUserLoggedIn },
        { title: 'sign_out', to: '/sign_out',
            showButton: this.$store.state.auth.isUserLoggedIn }
      ]
    }
  }
}
</script>

EDIT 1: Solution using mapGetters 编辑1:使用mapGetters的解决方案

Menu.vue Menu.vue

<script>
import { mapGetters } from 'vuex'

export default {
  data () {
    return { ... }
  },
  computed: {
    ...mapGetters([
      'isUserLoggedIn'
    ]),
    rightMenu () {
      return [
        { title: 'sign_in', to: '/sign_in', 
            showButton: !this.$store.state.auth.isUserLoggedIn },
        { title: 'sign_up', to: '/sign_up', 
            showButton: !this.$store.state.auth.isUserLoggedIn },
        { title: 'sign_out', to: '/sign_out',
            showButton: this.$store.state.auth.isUserLoggedIn }
      ]
    }
  }
}
</script>

store.js store.js

I've added the following getter: 我添加了以下getter:

...
getters: {
  isUserLoggedIn (state) {
    return state.auth.isUserLoggedIn
  }
}
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM