Vuex $store properties not reactive when using computed property

后端 未结 6 489
孤街浪徒
孤街浪徒 2020-12-29 23:03

I have a Vuex store, which I\'m injecting into my instance:

import store from \'../store\';

const mainNav = new Vue({
  el: \'#main-nav\',
  store,
  compon         


        
相关标签:
6条回答
  • 2020-12-29 23:04

    you should not manipulate store objects directly from component methods, you should commit mutations on store object. Mutations are functions that have listeners and when called changed variables are tracked and changes are propagated. If you need to do something async like submit data to the server you have to go even one step further define actions on the store, do async call and then commit mutations from there to update state object. I know this sounds so annoying but once you use to it it is pretty straight forward.

    const store = new Vuex.Store({
      state: {
        nav: {
          type: 'not wide by default'
        }
      },
      mutations: {
        changeType: (state, type) => {
          state.nav.type = type;
        }
      }
    })
    
    Vue.component('NavComponent', {
      template: '<div>isWide?: {{isWide}}</div>',
      computed: {
        isWide () {
          return this.$store.state.nav.type === 'wide'
        }
      }
    })
    
    new Vue({
      el: '#app',
      store,
      methods: {
        changeType (type) {
          this.$store.commit('changeType', type);
        }
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.1.0/vuex.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.js"></script>
    <div id="app">
      <nav-component></nav-component>
      <button @click="changeType('wide')">
        Change to Wide
      </button>
      <button @click="changeType('narrow')">
        Change to Narrow
      </button>
    </div>

    https://codepen.io/zoransa/pen/KyqvWd?editors=1010

    it also works directly at stat.nav without type https://codepen.io/zoransa/pen/xPrLyW?editors=1010

    0 讨论(0)
  • 2020-12-29 23:06

    Your code should work if you setup everything correctly: http://codepen.io/CodinCat/pen/RKZeZe?editors=1010

    A very common mistake is that you didn't give your state initial data.

    You should declare the state shape explicitly, so instead of

    state: {}
    
    // or
    
    state: {
      nav: {}
    }
    

    do this:

    state: {
      nav: {
        type: '...'
      },
      ...
    }
    

    or the properties will not be reactive, like this example: http://codepen.io/CodinCat/pen/ggxBEV?editors=1010

    And make sure you did update the state, maybe the problem is just you didn't update the state correctly as you expected.

    0 讨论(0)
  • 2020-12-29 23:09

    This was my problem.

      const store = new Vuex.Store({
        state: {
          isTrackPlaying: false,
        },
      ...
      });
    

    I forgot to set the initial state and now it is reactive.

    0 讨论(0)
  • 2020-12-29 23:16

    This is how I solved the problem:

    I have state objects which contain other objects. I tried using Vue.set whenever there is a mutation, but it was messy and still didn't work. So I created a boolean state variable called toggleState, and provided a getter for it. Whenever a mutation changes a main state object, it also does state.stateToggle =! state.stateToggle. Anyone who cares can watch for changes to stateToggle, and do whatever is needed. In my case, it's re-building a treeview with the mutated main objects.

    0 讨论(0)
  • 2020-12-29 23:26

    Actually, you need to use Vue.set() function to make the new property reactive.

    changeType () {
       Vue.set(this.$store.state.nav, 'type', 'wide');
    }
    

    See this codepen: https://codepen.io/DedicatedManager/pen/JZgpaa

    I did a whole screen capture video on this subject: youtu.be/8GHczab2Lbs

    0 讨论(0)
  • 2020-12-29 23:26

    When adding new properties to an Object from your Vuex store, you should either use

    Vue.set(obj, 'newProp', 123)
    

    or replace that Object with a fresh one

    state.obj = { ...state.obj, newProp: 123 }
    

    From Vuex docs

    0 讨论(0)
提交回复
热议问题