Vue и Vuex: вычисляемое свойство не вызывается при изменении состояния - PullRequest
1 голос
/ 07 августа 2020

Я новичок в Vue и Vuex, так что терпите меня.

Я хочу, чтобы вычисляемая функция versions() вызывалась при изменении state.template, но я терплю неудачу сделать так. В частности, при изменении state.template.versions.

Это часть компонента, который я хочу повторно визуализировать при изменении state.template.versions. Вы также можете увидеть вычисленное свойство 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
        })
    },

Это getter:

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

Это 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)
      })

Это mutation:

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

Я читал, что в некоторых случаях Vue не обнаруживает ченеги, сделанные в массив, но .push() вроде бы обнаружен. Источник: https://vuejs.org/v2/guide/list.html#Caveats

Есть идеи, почему вычисляемое свойство не вызывается при обновлении context.state.template.versions?

Ответы [ 3 ]

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

Проблема может исходить от state.template = template. Вы правильно угадали, что это проблема реактивности, но не из-за реактивности массива, а из-за объекта template.

Vue не может обнаружить добавление или удаление свойств. Это включает в себя влияние на свойство сложного объекта. Для этого вам нужно использовать Vue.set.

Итак, ваша мутация должна быть:

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

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

1 голос
/ 07 августа 2020

Ваша функция не будет вызвана, потому что это неверно:

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

объект context.state просто указывает на ваше текущее состояние, ничего больше.

Мое предлагаемое решение будет:

  1. Сначала вам нужно правильно объявить состояние вашего магазина

    state: {
       template: {
          versions: []
       }
    }
    
  2. Вам нужно обновить геттер, чтобы он выглядел так, без лишних условий :

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

  3. добавить новую мутацию

     ADD_VERSION: (state, version) => {
       state.template = {
         ...state.template,
         versions: [...state.template.versions, version]
        };
      }
    
  4. теперь ваше действие должно выглядеть так:

       createProductionVersion({commit}, data) {
           return new Promise((resolve, reject) => {
             documentsService.createProductionVersion(data).then(result => {
               commit('ADD_VERSION', data);
               resolve(result);
             });
           });
         }
    
  5. В вашем компоненте я предлагаю изменить ваше вычисляемое свойство с функции на объект, содержащий методы get и set (set необязательно)

    versions: {
      get() {
        return this.documentVersions.map(function (version) {
          const v = {
            id: version.id,
            name: 'Draft Version',
            effectiveDate: '',
            status: 'Draft version',
          }
          return v
        })
      }
    },
    
1 голос
/ 07 августа 2020

Я думаю, эта ошибка возникла из-за того, что вы неправильно объявили состояние своего магазина. Убедитесь, что у вас есть свойство versions в вашем объекте template.

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

Таким образом, любые изменения в свойстве versions будут обнаружены vue.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...