Принудительно обновлять реквизиты в дочернем компоненте после обновления Vuex

У меня есть дочерний компонент (<BaseProjectTable>), который повторно используется на моем сайте, содержащем Vuetify <v-data-table>составная часть. Заголовки и элементы содержимого для таблицы данных передаются в компонент как реквизиты, а данные элемента отображаются в родительский элемент какmapGetterиз магазина Vuex. Дочерний компонент содержит функции редактирования для каждой строки, и я используюmapActionдля обновления данных API и Vuex оттуда, при этом идея состоит в том, что, поскольку мой mapGetter является реактивным, он должен обновлять данные и, следовательно, отображение таблицы данных. Однако это не работает; С помощью инструментов разработчика я могу видеть, что состояние обновляется нормально, а отображение дочернего компонента - нет.

Вот соответствующая часть ребенка <BaseProjectTable> составная часть:

<template>
  <div>
    <v-data-table
      show-expand
      :headers="headers"
      :items="filteredItems"
      :search="search"
      tem-key="sow"
      @click:row="rowClick"
      :hide-default-footer="disablePagination"
      dense
      :disable-pagination="disablePagination"
    >
    ...
    </v-data-table>

    ...
    export default {
    name: "BaseProjectTable",
    props: {
      headers: Array,
      items: Array,
      loggedInUser: Object,
      title: String,
      max2chars: v => v.length <= 2 || 'Input too long!',
      editDialog: false,
      showPracticeFilter: {
        default: true,
        type: Boolean
      },
      showSEFilter: {
        default: true,
        type: Boolean
      },
      showStatusFilter: {
        default: true,
        type: Boolean
      },
      projectType: {
        type: String,
        default: 'active'
      },
      disablePagination: {
        type: Boolean,
        default: true
      },
    },
  },
  methods: {
  ...mapActions('projects', {
        saveProject: 'saveProject',
    }), 
    save() {
      // Update API and store with new data.
      this.saveProject({
        projectType: this.projectType,
        projectData: this.editedItem
      })
  },
  computed: {
      statuses()  {
        return this.projectType === 'active' ? this.activeStatuses : this.oppStatuses;
      },
      filteredItems() {
        return this.items.filter(d => {
          return Object.keys(this.filters).every(f => {
            return this.filters[f].length < 1 || this.filters[f].includes(d[f])
          })
        })
      },
    }

и вот соответствующий код из родительского компонента:

<v-card>
  <BaseProjectTable
    :headers="headers"
    :items="activeProjects"
    :loggedInUser="loggedInUser"
    title="Active Projects"
    :disablePagination=false
  ></BaseProjectTable>
</v-card>
...
export default {
  computed: {
    ...mapGetters('projects', {
      activeProjects: 'activeProjects',
      closedProjects: 'closedProjects',
      opportunities: 'opportunities'
    }),
  }
}

В save() обновляет данные в моем хранилище Vuex, на которые ссылается activeProjectsmap getter (я проверил в Vue devtools, что это правда). Он также показываетitems значение в самом компоненте обновляется в Componentsвкладка в инструментах разработчика. Поскольку использованиеmapGetters делает данные реактивными, я ожидал, что он также обновит данные в моем дочернем компоненте, но это не так.

Основываясь на том, что я здесь увидел, я попробовалitem-key свойство <v-data-table> вот так:

<v-data-table
  show-expand
  :headers="headers"
  :items="filteredItems"
  :search="search"
  item-key="sow"
  @click:row="rowClick"
  :hide-default-footer="disablePagination"
  dense
  :disable-pagination="disablePagination"
>

(каждая запись, использующая этот компонент, будет иметь уникальный sow key), но это не сработало.

Единственное, что я мог подумать, это то, как я редактирую данные в своей мутации:

export const state = () => ({
    active: [],
    closed: [],
    opportunities: [],
})

export const getters = {
  activeProjects: state => state.active,
  closedProjects: state => state.closed,
  opportunities: state => state.opportunities,
}

export const actions = {
  saveProject({ commit }, {projectType, projectData}) {
    commit(types.SAVE_PROJECT, {projectType, projectData});
  }
}

export const mutations = {
  [types.SAVE_PROJECT](state, {projectType, projectData}) {
    // Get project from state list by sow field.
    const index = state[projectType].findIndex(p => p.sow === projectData.sow);
    state[projectType][index] = projectData;
  }
}

по сравнению с заменой всего state[projectType] значение.

Что мне нужно сделать, чтобы таблица данных отображала мое обновленное значение?

1 ответ

Решение

Из документации Vue,

Vue не может обнаружить следующие изменения в массиве

  • Когда вы напрямую устанавливаете элемент с индексом, например vm.items[indexOfItem] = newValue
  • Когда вы изменяете длину массива, например vm.items.length = newLength

Замени то, что у тебя есть

import Vue from 'vue'; // this should be at the top level

export const mutations = {
  [types.SAVE_PROJECT](state, {projectType, projectData}) {
    // Get project from state list by sow field.
    const index = state[projectType].findIndex(p => p.sow === projectData.sow);
    Vue.set(state[projectType], index, projectData)
  }
}

После этого изменения в массиве будут обнаружены, и геттер будет работать должным образом.

Другие вопросы по тегам