Vuex Store 和 Vue Component 之间数据不同步

Data not syncing between Vuex Store and Vue Component

我在目前正在进行的 Quasar 项目的一个组件中遇到了问题。我目前正在使用 Q-table 从数据字段中提取信息。该数据字段被赋予 Vuex 存储中数据字段的值,该数据字段应该自动同步,但事实并非如此。如果我离开组件并返回到它,那么数据字段会发生变化,但是每当我在组件上时,组件似乎都不会重新加载以同步数据。任何帮助,将不胜感激 Vuex Store 代码如下:

import { Module, VuexModule, getModule, Mutation, Action } from 'vuex-module-decorators'
import { websocket } from 'src/boot/socket.io-client'
import store from 'src/store'
import { AcademicProgramData, AcademicProgramPagination, AcademicProgramQualification, AcademicProgramStatus } from './types'
export { AcademicProgramData, AcademicProgramPagination, AcademicProgramStatus, AcademicProgramQualification } from './types'

export interface AcademicProgramState {
  data: AcademicProgramData [],
  filter: string,
  statuses: AcademicProgramStatus [],
  qualifications: AcademicProgramQualification [],
  pagination: AcademicProgramPagination
}

@Module({
  name: 'academicProgram',
  namespaced: true,
  dynamic: true,
  store
})

class AcademicProgram extends VuexModule implements AcademicProgramState {
  public data: AcademicProgramData []= []

  public filter: string = ''
  public statuses: AcademicProgramStatus [] = []
  public qualifications: AcademicProgramQualification [] = []
  public pagination: AcademicProgramPagination = {
    descending: true,
    rowsNumber: 10,
    rowsPerPage: 10,
    page: 1,
    sortBy: 'name'
  }
  get getData() {
    return this.data
  }

  @Mutation 
  public SET_PAGINATION(pagination: AcademicProgramPagination) {
    this.pagination = pagination
  }

  @Mutation
  public SET_FILTER(filter: string) {
    this.filter=filter
  }

  @Mutation
  public SET_DATA (data: AcademicProgramData []) {
    this.data = data
  }

  @Mutation 
  public SET_STATUSES (statuses: AcademicProgramStatus []) {
    this.statuses=statuses
  }

  @Mutation 
  public SET_QUALIFICATIONS (qualifications: AcademicProgramQualification []) {
    this.qualifications=qualifications
  }

  @Mutation
  public SET_PAGINATION_VARS (total: number, listtotal: number)
  {
    this.pagination.rowsNumber=total
  }

  @Action
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  public async fetchData() {
    let dir: string=''
    if(this.pagination.descending===true) {
      dir='DESC'
    }
    else {
      dir='ASC'
    } 
    await websocket.emit('query', `{
      academicPrograms(
        page: {
          skip: 0
          first: ${this.pagination.rowsPerPage}
        }
        filter: {
          ilike: {
            name: "${this.filter}"
          }
        }
        order: {
          by: ${this.pagination.sortBy}
          dir: ${dir}
        }
      ) {
        pagination {
          total
          listTotal
        }
        list {
          id
          name
          code
          type {
            id
            name
          }
          status {
            id
            name
          }
        }
      }
    }`, (response: { errors: any; data: { academicPrograms: { list: AcademicProgramData[]; pagination: { total: number; listTotal: number; } } } }) => {
      console.log(response.data.academicPrograms.list)
      this.SET_DATA(response.data.academicPrograms.list)
      this.SET_PAGINATION_VARS(response.data.academicPrograms.pagination.total, response.data.academicPrograms.pagination.listTotal)
    })
  }

  @Action
  public async getQualifications() {
    await websocket.emit('query', `{
      academicProgramTypes
      {
        pagination {
          total
          listTotal
        }
        list {
          id
          name
        }
      }
    }`, (response: { errors: any; data: { academicProgramTypes: { list: AcademicProgramData []; pagination: { total: number } } } }) => {
      this.SET_QUALIFICATIONS(response.data.academicProgramTypes.list)
    })
  }

  @Action
  public async getStatuses() {
    await websocket.emit('query', `{
      academicProgramStatuses
      {
        pagination {
          total
          listTotal
        }
        list {
          id
          name
        }
      }
    }`, (response: { errors: any; data: { academicProgramStatuses: { list: AcademicProgramData []; pagination: { total: number } } } }) => {
      this.SET_STATUSES(response.data.academicProgramStatuses.list)
    })
  }

  @Action
  public async addAcademicProgram(input: AcademicProgramData) {
    await websocket.emit('query', `mutation {
      createAcademicProgram (
        academicProgram: {
          code: "${input.code}"
          name: "${input.name}"
          typeId: "${input.type.id}"
          statusId: "${input.status.id}"
        }
      ) {
        id
        ok
        message
      }
  }`, (response: {errors: any; data: {id: any; ok: boolean; message: String} } ) => {
      console.log(response)
    })
  }

  @Action
  public async editAcademicProgram(input: AcademicProgramData) {
    await websocket.emit('query', `mutation {
      updateAcademicProgram (
        academicProgram: {
          id: "${input.id}"
          code: "${input.code}"
          name: "${input.name}"
          typeId: "${input.type.id}"
          statusId: "${input.status.id}"
        }
      ) {
        id
        ok
        message
      }
    }`, (response: {errors: any; data: {id: any; ok: boolean; message: String}}) => {
      console.log(response)
    })
  }

  @Action
  public async deleteAcademicProgram(input: AcademicProgramData) {
    await websocket.emit('query', `mutation {
      deleteAcademicProgram (
        academicProgramId: "${input.id}"
      ) {
        id
        ok
        message
      }
    }`, (response: {errors: any; data: {id: any; ok: boolean; message: String } }) => {
      console.log(response)
    })
  }
}

export const AcademicProgramModule = getModule(AcademicProgram)

我的组件代码如下:

<template>
  <div>
    <q-toolbar
      class="bg-grey-1 text-subtitle1 text-blue-grey-8 shadow-2 rounded-borders"
    >
      <q-breadcrumbs class="text-grey" active-color="primary">
        <template v-slot:separator>
          <q-icon size="24px" name="arrow_forward" color="primary" />
        </template>

        <q-breadcrumbs-el
          label="Settings"
          icon="settings"
          class="hover cursor-pointer"
          @click="$router.push('/system')"
        />
        <q-breadcrumbs-el
          label="Academic Program"
          icon="description"
        />
      </q-breadcrumbs>
    </q-toolbar>
    <q-table class="q-mt-sm" 
      :columns="columns" 
      :data.sync="data"
      :pagination.sync="pagination"
      row-key="id"
      selection="single"
      :selected.sync="selected"
      @request="changePagination"
    >
      <template slot="top">

        <q-input
          v-model="filter"
          clearable
          placeholder="Search by Academic Program"
          type="text"
          class="col-3"
          @keypress.enter.native="search"
        />
        <q-btn
          class="q-pl-sm q-pr-sm"
          color="primary"
          flat
          @click="$refs.addAcademicProgram.toggle()"
        >
          <q-icon name="fas fa-plus" />
          <q-tooltip
            anchor="top middle"
            self="bottom middle"
            :offset="[10, 10]"
          >
            <strong>Add new Academic Program</strong>
          </q-tooltip>
        </q-btn>
        <q-btn
          class="q-pl-sm"
          color="primary"
          :disable="!selected.length"
          flat
          @click="$refs.editAcademicProgram.toggle()"
        >
          <q-icon name="fas fa-pencil-alt" />
          <q-tooltip
            anchor="top middle"
            self="bottom middle"
            :offset="[10, 10]"
          >
            <strong>Edit Academic Program</strong>
            <br />Select record first
          </q-tooltip>
        </q-btn>
        <div class="col" />
        <q-btn
          color="negative"
          :disable="!selected.length"
          flat
          round
          @click="$refs.deleteAcademicProgram.toggle()"
        >
          <q-icon name="fas fa-trash-alt" />
          <q-tooltip
            anchor="top middle"
            self="bottom middle"
            :offset="[10, 10]"
          >
            <strong>Delete Academic Program</strong>
            <br />Select record first
          </q-tooltip>
        </q-btn>
      </template>
    </q-table>
    <addAcademicProgram ref="addAcademicProgram"></addAcademicProgram>
    <editAcademicProgram
      :data="selected"
      ref="editAcademicProgram"
    ></editAcademicProgram>
    <deleteAcademicProgram :data="selected" ref="deleteAcademicProgram"></deleteAcademicProgram>
  </div>
</template>

<script lang="ts">
import { Vue, Component, Watch } from 'vue-property-decorator'
import { AcademicProgramModule, AcademicProgramQualification, AcademicProgramStatus, AcademicProgramData, AcademicProgramPagination } from 'src/store/academicProgram'
import AddAcademicProgram from './AddAcademicPrograms.vue'
import EditAcademicProgram from './EditAcademicPrograms.vue'
import DeleteAcademicProgram from './DeleteAcademicPrograms.vue'

@Component({
  components: {
    addAcademicProgram: AddAcademicProgram,
    editAcademicProgram: EditAcademicProgram,
    deleteAcademicProgram: DeleteAcademicProgram
  }
})
export default class ManageAcademicProgram extends Vue {
  private filter: string = AcademicProgramModule.filter
  private selected: AcademicProgramData [] = []
  private pagination: AcademicProgramPagination = AcademicProgramModule.pagination

  private columns = [
    {
      name: 'code',
      label: 'Code',
      align: 'center',
      required: true,
      field: 'code',
      sortable: true
    },
    {
      name: 'name',
      label: 'Name',
      align: 'center',
      required: true,
      field: 'name',
      sortable: true
    },

  ]

  private getstatuses: AcademicProgramStatus [] = AcademicProgramModule.statuses

  private qualifications: AcademicProgramQualification [] = AcademicProgramModule.qualifications

  private data: AcademicProgramData [] = AcademicProgramModule.data

  changePagination() {
    AcademicProgramModule.SET_PAGINATION(this.pagination)
    AcademicProgramModule.fetchData()
  }

  search() {
    console.log("Searched")
    if(this.filter===null)
    {
      this.filter=''
    }

    AcademicProgramModule.SET_FILTER(this.filter)
    AcademicProgramModule.fetchData()

    console.log('component data... ',this.data)
  }

  beforeMount() {
    AcademicProgramModule.fetchData()
    AcademicProgramModule.getStatuses()
    AcademicProgramModule.getQualifications()
  }
}
</script>

在我看来,您在组件中使用 reference1 分配数据,并期望它在您更改 vuex 存储中的任何其他变量时更改其引用。使用商店参考获取您的数据数组

AcademicProgramModule.data = [1,2,3]
...
private data: AcademicProgramData [] = AcademicProgramModule.data

...
AcademicProgramModule.data = [4,5,6]
...
console.log(data) // [1,2,3]

//better

get data(){
  return AcademicProgramModule.data
}