简体   繁体   English

Vue 和 Vuex:更改 state 时不调用计算属性

[英]Vue and Vuex: computed property isn't called when changing state

I'm quite new with Vue and Vuex so please bear with me.我对 Vue 和 Vuex 很陌生,所以请多多包涵。

I want to make the computed function versions() get called when I change state.template , but I'm failing to do so.我想在更改state.template时调用计算的 function versions() ,但我没有这样做。 More specifically, when state.template.versions changes.更具体地说,当state.template.versions发生变化时。

This is part of the component that I want to re-render when state.template.versions changes.这是当state.template.versions更改时我想要重新渲染的组件的一部分。 You can also see the computed property versions() which I want to be called:您还可以看到我想要调用的计算属性versions()

    <el-dropdown-menu class="el-dropdown-menu--wide"
      slot="dropdown">
      <div v-for="version in versions"
        :key="version.id">
           ...
      </div>
    </el-dropdown-menu>
    ...
    computed: {
      ...mapState('documents', ['template', 'activeVersion']),
      ...mapGetters('documents', ['documentVersions', 'documentVersionById', 'documentFirstVersion']),
    versions () {
       return this.documentVersions.map(function (version) {
          const v = {
            id: version.id,
            name: 'Draft Version',
            effectiveDate: '',
            status: 'Draft version',
          }
          return v
        })
    },

This is the getter :这是getter

  documentVersions (state) {
    return state.template ? state.template.versions : []
  },

This is the action :这是action

  createProductionVersion (context, data) {
    return new Promise((resolve, reject) => {
      documentsService.createProductionVersion(data).then(result => {
        context.state.template.versions.push(data)  // <-- Here I'm changing state.template. I would expect versions() to be called
        context.commit('template', context.state.template)

        resolve(result)
      })

This is the mutation :这是mutation

  template (state, template) {
    state.template = template
  },

I've read that there are some cases in which Vue doesn't detect chanegs made to an array, but .push() seems to be detected.我读过在某些情况下 Vue 没有检测到对数组进行的更改,但似乎检测到了.push() Source: https://v2.vuejs.org/v2/guide/list.html#Caveats来源: https://v2.vuejs.org/v2/guide/list.html#Caveats

Any idea on why the computed property is not being called when I update context.state.template.versions ?关于我更新context.state.template.versions时为什么不调用计算属性的任何想法?

The issue may come from state.template = template .问题可能来自state.template = template You guessed correctly that it was a reactivity issue, but not from the Array reactivity, but the template object.你猜对了,这是一个反应性问题,但不是来自阵列反应性,而是template object。

Vue cannot detect property addition or deletion. Vue 无法检测到属性添加或删除。 This includes affecting a complex object to a property.这包括将复杂的 object 影响到属性。 For that, you need to use Vue.set .为此,您需要使用Vue.set

So your mutation should be:所以你的突变应该是:

template (state, template) {
  Vue.set(state, "template", template)
},

https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

I think this error occurred because you did not declare your store state correctly.我认为发生此错误是因为您没有正确声明您的商店 state。 Make sure you have the versions property in your template object.确保您的template object 中有versions属性。

state: {
  template: {
    versions: []
  }
}

This way, any changes in the versions property will be detected by vue.这样,vue 将检测到versions属性中的任何更改。

Your function won't get called because this is wrong:您的 function 不会被调用,因为这是错误的:

context.state.template.versions.push(data) 
context.commit('template', context.state.template)

the context.state object just points to your current state nothing more. context.state object 仅指向您当前的 state 仅此而已。

My suggested solution will be:我建议的解决方案是:

  1. First You need to declare your store state correctly首先您需要正确声明您的商店 state

     state: { template: { versions: [] } }
  2. You need to update your getter to look like this with no unnecessary conditioning:您需要更新您的吸气剂,使其看起来像这样,没有不必要的条件:

    documentVersions: state => return state.template.versions,

  3. add a new mutation添加一个新的突变

     ADD_VERSION: (state, version) => { state.template = {...state.template, versions: [...state.template.versions, version] }; }
  4. your action should like this now:你的动作现在应该是这样的:

     createProductionVersion({commit}, data) { return new Promise((resolve, reject) => { documentsService.createProductionVersion(data).then(result => { commit('ADD_VERSION', data); resolve(result); }); }); }
  5. In your component I suggest to change your computed property from a function to an object that contains a get and set methods ( set is optional)在您的组件中,我建议将您的计算属性从 function 更改为包含getset方法的 object( set是可选的)

     versions: { get() { return this.documentVersions.map(function (version) { const v = { id: version.id, name: 'Draft Version', effectiveDate: '', status: 'Draft version', } return v }) } },

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM