V-Snackbar не отображается, когда я обновляю состояние Vuex - PullRequest
1 голос
/ 01 августа 2020

Кажется, я не могу понять, почему мой компонент <v-snackbar> не отображается, когда я обновляю состояние Vuex.

Моя настройка очень проста: у меня есть закусочная в Snackbar. js, который отслеживает изменения в состоянии.

This Snackbar. js импортируется как дочерний компонент в App. vue так что его глобальный.

Далее у меня есть Test . vue с простой кнопкой. Я ожидаю, что, когда я нажму кнопку, состояние должно обновиться, а панель закусок должна отобразиться, но это не так.

Проверив компонент Snackbar в Chrome Vue Devtools, Я мог видеть, что данные действительно попадают в магазин, но каким-то образом не обновляют реактивные реквизиты в Test. vue enter image description here

Here are the relevant codes:


Snackbar.vue

<template>
  <v-snackbar v-model="show" :top="top" multi-line rounded="pill">
    {{ text }}
    <v-btn text @click.native="show = false">
      <v-icon>close</v-icon>
    </v-btn>
  </v-snackbar>
</template>

<script>
import { mapState } from 'vuex'
export default {
  data () {
    return {
      show: false,
      text: '',
      top: true
    }
  },
  computed: {
    ...mapState(['snackbar'])
  },
  created: () => {
    this.unwatch = this.$store.watch(
      // watch snackbar state
      (state, getters) => getters.snackbar,
      () => {
        const text = this.$store.state.snackbar.text
        if (text) {
          this.show = true
          this.text = text
        } 
      }
    )
  },
  beforeDestroy () {
    this.unwatch()
  }
}
</script>

Прил. vue

<template>
  <v-app>
    <v-main>
      <!-- try to set a global snackbar -->
      <Snackbar/>
      <router-view/>
    </v-main>
  </v-app>
</template>

<script>
import Snackbar from '@/components/Snackbar'

export default {
  name: 'App',
  components: {
    Snackbar
  }
}
</script>

Тест. vue

<template>
    <v-btn @click="passData">Show snackbar</v-btn>
</template>

<script>
import { mapActions } from 'vuex'
export default {
  name: 'Test',
  data: () => ({
    //
  }),
  computed: {},
  methods: {
    ...mapActions([
      'setSnackbar'
    ]),
    passData () {
      this.setSnackbar({
        text: 'Simple message',
        isActive: true
      })
    }
  }
}
</script>

Магазин / индекс. js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    snackbar: {
      isActive: false,
      text: ''
    }
  },
  getters: {
    snackbar (state) {
      return state.snackbar
    }
  },
  mutations: {
    populateSnackbar (state, payload) {
      state.snackbar.isActive = payload.isActive
      state.snackbar.text = payload.text
    }
  },
  actions: {
    setSnackbar (context, payload) {
      context.commit('populateSnackbar', payload)
    }
  }
})

1 Ответ

2 голосов
/ 01 августа 2020

Приведенный выше код будет показывать снэк-бар в первый раз из-за созданного хука, и в следующий раз он не будет работать, это связано с Vue реактивностью

Здесь состояние будет обновлено, но данные свойства в компоненте закусочной панели не получены обновленные данные

Компонент закусочной панели можно заменить на

<template>
  <v-snackbar v-model="snackbar.show" :top="top" multi-line rounded="pill">
    {{ snackbar.text }}
    <v-btn text @click.native="$store.dispatch('setSnackbar', {text: '', isActive: false})">
      <v-icon>close</v-icon>
    </v-btn>
  </v-snackbar>
</template>

<script>
import { mapState } from 'vuex'
export default {
  computed: {
    ...mapState(['snackbar'])
  },
...