Vue.js:当用户登录时,根据Vuex Store状态显示/隐藏导航栏上的按钮

问题描述 投票:0回答:2

我正在创建一个显示或隐藏按钮的导航栏,具体取决于用户是否登录。为此,我将状态保存在Vuex和localStorage上。

我正在尝试构建一个动态菜单,使用包含按钮信息的对象列表(即rightMenu)(即路由,标题和标志,指示如果用户登录,按钮是否显示) 。

用户一直登录系统,this.$store.state.auth.isUserLoggedIn会更改为true,但模板不会更改,当用户未登录时,按钮会保持相同的初始状态。例如:当sign out更新时,this.$store.state.auth.isUserLoggedIn按钮不会显示。但是当我点击“ctrl + F5”并重新加载页面时,按钮显示正确。在这种情况下,例如,当我手动重新加载页面时,sign out按钮正确显示。

我正在考虑在用户登录或注销时强制页面重新加载,但我相信这不是一个好选择。

谁能帮助我?

我正在给出我正在使用的代码。

先感谢您。

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>脚本

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

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))
    }
  }
  ...
})

编辑1:

当我在我的代码中明确使用this.$store.state.auth.isUserLoggedIn时,它运行良好。因此,按钮会出现并正确消失。我举一个例子:

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>

因此,我认为问题在于showButtonthis.$store.state.auth.isUserLoggedIn的约束。

javascript vue.js local-storage vuex vue-cli-3
2个回答
1
投票

使用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>

0
投票

通过Chris Li,Andrei Gheorghiu和Sajib Khan的答案,我可以解决我的问题。

Andrei Gheorghiu解释说我无法访问data()中的计算属性,Chris Li建议我使用计算变量代替。这些答案加上Sajib Khan的例子,我能够在下面分享的解决方案中思考。我希望将来能帮助别人。

简而言之,我创建了一个返回我的数组的计算属性,并且当this.$store.state.auth.isUserLoggedIn更新时,数组一起更改(因此菜单也是如此)。

我打算为我的this.$store.state.auth.isUserLoggedIn创建一个mapGetter。一旦我这样做,我就会更新答案。

非常感谢你们。

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

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

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

我添加了以下getter:

...
getters: {
  isUserLoggedIn (state) {
    return state.auth.isUserLoggedIn
  }
}
...
© www.soinside.com 2019 - 2024. All rights reserved.