38

我有一个 Vuex 商店,我将其注入到我的实例中:

import store from '../store';
    
const mainNav = new Vue({
  el: '#main-nav',
  store,
  components: { NavComponent }
});

我正在组件中从该商店创建一个计算属性:

computed: {
  isWide() {
    return this.$store.state.nav.type === 'wide';
  }
}

这确实this.isWide在组件初始化时为模板创建了属性,但是当更新存储值时,组件不会注册它 - 旧值仍在模板上。

我在这里做错了什么?

4

8 回答 8

52

如果您正确设置所有内容,您的代码应该可以工作:http ://codepen.io/CodinCat/pen/RKZeZe?editors=1010

一个非常常见的错误是您没有提供您所在州的初始数据。

您应该明确声明状态形状,而不是

state: {}

// or

state: {
  nav: {}
}

做这个:

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

或者属性不会是反应性的,例如这个例子:http ://codepen.io/CodinCat/pen/ggxBEV?editors=1010

并确保您确实更新了状态,也许问题只是您没有按预期正确更新状态。

于 2017-01-25T16:10:07.650 回答
11

实际上,您需要使用 Vue.set() 函数来使新属性具有反应性。

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

请参阅此代码笔: https ://codepen.io/DedicatedManager/pen/JZgpaa

我为此主题制作了一个完整的屏幕截图视频:youtu.be/8GHczab2Lbs

于 2018-07-09T16:25:29.227 回答
10

Vuex商店向对象添加新属性时,您应该使用

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

或用新的对象替换该对象

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

来自Vuex 文档

于 2019-11-08T15:52:35.510 回答
2

您不应该直接从组件方法操作存储对象,您应该在存储对象上提交突变。突变是具有侦听器的函数,在调用时会跟踪更改的变量并传播更改。如果你需要做一些异步的事情,比如向服务器提交数据,你甚至必须进一步定义存储上的操作,进行异步调用,然后从那里提交突变以更新状态对象。我知道这听起来很烦人,但是一旦你习惯了它就很简单了。

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

它也可以直接在 stat.nav 中使用,无需输入 https://codepen.io/zoransa/pen/xPrLyW?editors=1010

于 2017-11-13T22:03:43.443 回答
0

这是我的问题。

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

我忘了设置初始状态,现在它是反应性的。

于 2018-11-09T20:40:52.780 回答
0

这就是我解决问题的方法:

我有包含其他对象的状态对象。每当发生突变时,我都尝试使用 Vue.set,但它很混乱,仍然无法正常工作。所以我创建了一个名为 toggleState 的布尔状态变量,并为它提供了一个 getter。每当一个突变改变一个主要的状态对象时,它也会改变state.stateToggle =! state.stateToggle。任何关心的人都可以观察 stateToggle 的变化,并做任何需要的事情。就我而言,它正在使用变异的主要对象重新构建树视图。

于 2020-06-27T16:11:53.750 回答
0

就我而言,我只是忘记在我的突变中传递变量“状态”,因此,它不是反应性的

const mutations = {
  [mutationTypes.storeTaskStart](state) {
    state.isSubmitting = true;
  },
};
于 2022-01-01T11:41:23.947 回答
-1

两者都是反应性的

$vm.$set

this.$set(some_object, 'key', 'value')

Vue.set

Vue.set(some_object, 'key', 'value')
于 2021-04-21T19:14:41.087 回答