我正在创建一个显示或隐藏按钮的导航栏,具体取决于用户是否登录。为此,我将状态保存在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>
因此,我认为问题在于showButton
与this.$store.state.auth.isUserLoggedIn
的约束。
使用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>
通过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
}
}
...