Vuex 업데이트 후 하위 구성 요소에서 소품 업데이트 강제

Aug 21 2020

<BaseProjectTable>Vuetify <v-data-table>구성 요소 를 포함하는 내 사이트 전체에서 재사용 되는 하위 구성 요소 ( )가 있습니다 . 데이터 테이블의 헤더 및 콘텐츠 항목은 소품으로 구성 요소에 전달되고 항목 데이터는 mapGetterVuex 저장소에서 부모로 매핑됩니다 . 하위 구성 요소에는 각 행에 대한 편집 기능이 포함되어 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()메서드는 activeProjects맵 게터 가 참조하는 Vuex 저장소의 데이터를 업데이트합니다 (Vue devtools에서 이것이 사실인지 확인했습니다). 또한 개발 도구 itemsComponents탭에서 업데이트 된 구성 요소 자체 의 값을 보여줍니다 . 사용 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키가 있습니다)하지만 작동하지 않았습니다.

내가 생각할 수있는 유일한 생각은 내 돌연변이에서 데이터를 편집하는 방법입니다.

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]값 을 대체하는 것과 비교할 때 .

업데이트 된 값을 표시하기 위해 데이터 테이블을 가져 오려면 어떻게해야합니까?

답변

Tony Aug 21 2020 at 12:40

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)
  }
}

그 후에 배열의 변경 사항이 감지되고 getter가 예상대로 작동합니다.