Vue.js: Показать / Скрыть кнопки на панели навигации в зависимости от состояния магазина Vuex, когда пользователь вошел в систему или нет - PullRequest
0 голосов
/ 08 апреля 2019

Я создаю панель навигации, которая показывает или скрывает кнопки в зависимости от того, вошел пользователь в систему или нет. Для этого я сохраняю состояние в 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> script

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.

Ответы [ 2 ]

1 голос
/ 08 апреля 2019

Используйте свойство 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 голосов
/ 08 апреля 2019

Благодаря ответам Криса Ли, Андрея Георгиу и Саджиба Хана я смог решить мою проблему.

Андрей Георгиу объяснил, что я не могу получить доступ к вычисляемым свойствам в data(), и Крис Ли предложил вместо этого использовать вычисляемую переменную. Эти ответы плюс пример Саджиб Хана, который я смог найти в решении, которым я поделюсь ниже. Я надеюсь, что это поможет другим в будущем.

В двух словах, я создал вычисляемое свойство, которое возвращает мой массив, и всегда, когда this.$store.state.auth.isUserLoggedIn обновляется, массив изменяется вместе (следовательно, и меню).

Я намереваюсь создать mapGetter для моего this.$store.state.auth.isUserLoggedIn. Как только я это сделаю, я обновлю ответ.

Большое спасибо, ребята.

<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

Я добавил следующий метод получения:

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