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
}
我在目前正在进行的 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
}