使用计算 属性 (Vuex) 时 $store 属性不是反应性的

$store properties are not reactive when using computed property (Vuex)

我有一个 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 属性,但是当更新存储值时,组件不会注册它 - 旧值仍在模板上.

我做错了什么?

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

一个很常见的错误是你没有给你的状态初始数据。

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

state: {}

// or

state: {
  nav: {}
}

这样做:

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

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

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

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

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

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

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

查看此代码笔:https://codepen.io/DedicatedManager/pen/JZgpaa

我做了一个关于这个主题的全屏捕获视频:youtu。be/8GHczab2Lbs

这是我的问题。

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

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

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

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

或者用一个新的对象替换那个对象

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

来自Vuex docs

我是这样解决问题的:

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

两者都是反应性的

$vm.$set

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

Vue.set

Vue.set(some_object, 'key', 'value')

在我的例子中,我只是忘记在我的突变中传递变量 'state',因此,它不是反应性的

const mutations = {
  [mutationTypes.storeTaskStart](state) {
    state.isSubmitting = true;
  },
};