对 vuex 数据的更改未反映在 Quasar QTable 中
Changes to vuex data not reflected in Quasar QTable
我正在使用带有 Vuex 的 Quasar 将数据集加载到 QTable 中。它工作得很好,但我正在尝试使用 QPopupEdit 来更改项目的状态。数据是从一个Laravel API中拉取的,原始数据集是一个Laravel资源,所以我有项目,每个项目都有一个状态对象(item.status_id和状态:id , 状态:姓名等)
我已经在 q-table 之外公开了第一条记录的状态值,当我将更新推送到 API 时,我 return 更改了项目资源, 将它插入到 vuex mutation 中的 Vuex 数据中,它不会在 table.
中更新
<div v-if="items && items[0] && items[0].order">
{{items[0].status.id}} | {{items[0].status.name}}
</div>
<q-table
title="Projects"
:data="items"
:columns="columns"
color="primary"
row-key="id"
:loading="loading"
no-data-label="no projects with search prameters"
:visible-columns="visibleColumns">
<template v-slot:top="props">
<q-btn
flat round dense
:icon="props.inFullscreen ? 'fullscreen_exit' : 'fullscreen'"
@click="props.toggleFullscreen"
class="q-ml-md"
/>
<q-space />
<q-select
v-model="visibleColumns"
multiple
borderless
dense
options-dense
emit-value
map-options
:options="columns"
option-value="name"
style="min-width: 150px"
/>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td key="user" :props="props">
{{ props.row.order.user.firstname }} {{ props.row.order.user.lastname }}
</q-td>
<q-td key="name" :props="props">
{{ props.row.service.name }}
</q-td>
<q-td key="status" :props="props">
<q-badge v-if="props.row.status" :color="props.row.status.color" outline>
{{ props.row.status.name }}
</q-badge>
<q-popup-edit v-model="props.row.status.id" :key="item">
<q-select fill-input color="primary" v-model="props.row.status.id" :key="props.row" :options="statuses" label="Status" emit-value map-options option-label="name" @input="(val) => saveStatus(val, props.row, index)" />
</q-popup-edit>
{{props.row.status.id}} | {{props.row.status_id}}
</q-td>
<q-td key="updated_at" :props="props">
{{ formatDate(props.row.updated_at, 'MMM D, YYYY HH:mm A')}}
</q-td>
<q-td key="notes" :props="props">
<div class="table-description cursor-pointer">
<q-icon v-if="!props.row.notes" name="fal fa-comment-alt" class="float-right" />
{{ props.row.notes }}
<q-popup-edit
buttons
v-model="props.row.notes"
>
<q-input
type="textarea"
v-model="props.row.notes"
autofocus
counter
@keyup.enter.stop
/>
</q-popup-edit>
</div>
</q-td>
<q-td key="id" :props="props">
<q-btn icon="fal fa-arrow-right" :to="'/item/' + props.row.id" class="cursor-pointer" />
</q-td>
</q-tr>
</template>
</q-table>
脚本节选
import { mapState } from 'vuex'
import { date } from 'quasar'
export default {
data () {
return {
inFullscreen: false,
visibleColumns: [ 'user', 'name', 'status', 'updated_at', 'notes', 'id' ],
columns: [
{ name: 'user', align: 'left', label: 'Client', field: row => row.order.user.firstname, format: (val, row) => `${val}`, sortable: false },
{ name: 'name', required: true, label: 'Name', align: 'left', field: row => row.service.name, format: val => `${val}`, sortable: true },
{ name: 'status', align: 'left', label: 'Status', field: row => row.status.name, format: val => `${val}`, sortable: true },
{ name: 'updated_at', align: 'left', label: 'Last Updated', field: row => row.status.updated_at, format: val => `${val}`, sortable: true },
{ name: 'notes', align: 'left', label: 'Notes', field: 'notes', sortable: false },
{ name: 'id', align: 'right', label: 'Actions', field: 'id', sortable: false }
]
}
},
mounted () {
this.fetch()
if (!this.statuses || this.statuses.length < 1) {
this.$store.dispatch('items/fetchStatuses')
}
},
computed: {
...mapState({
loading: state => state.auth.loading,
authuser: state => state.auth.user,
pagination: state => state.items.pagination,
items: state => state.items.items,
statuses: state => state.items.statuses
})
},
methods: {
saveStatus (value, item, index) {
console.log(value + ' | ' + index)
console.log(item)
let payload = { 'status_id': value, 'item_id': item.id, 'index': index }
this.$store.dispatch('items/saveStatus', payload)
},
formatDate (dt, mask) {
return date.formatDate(date.extractDate(dt, 'YYYY-MM-DDTHH:mm:ss.SSSSSSZ'), mask)
},
fetch () {
this.$store.dispatch('auth/statusLoading', true)
this.$store.dispatch('items/fetchItems', this.id).then((res) => {
this.$store.dispatch('auth/statusLoading', false)
}).catch(error => {
if (error) {
console.log(error)
}
})
},
}
}
我的动作和来自 vuex 项目模块的变异
export function saveStatus ({ state, commit, getters }, payload) {
return new Promise((resolve, reject) => {
axiosInstance.post('/api/status/update/Item/' + payload.item_id, payload)
.then(response => {
// alert(JSON.stringify(response, null, 4))
let pl = { 'item': response.data.data }
commit('setIndexItem', pl)
resolve(null)
// console.log(response)
// commit('setItems', response.data.data)
})
.catch(err => {
reject(err)
})
})
}
export function setIndexItem (state, payload) {
var index = state.items.findIndex(i => i.id === payload.item.id)
state.items[index] = payload.item
}
我知道 Laravel API 部分正在工作 - 数据库中的值正在更新,更新状态的项目正在 returned 到 vuex 商店,这就是正在 vuex 存储库中更新,如公开的第一个调试元素所示,但在 QTable 中,它不会更新。
也许 Array Change Detection leads the view not updated. You can use the Vue.set 更新视图
import Vue from 'vue'
// ...
export function setIndexItem (state, payload) {
var index = state.items.findIndex(i => i.id === payload.item.id)
Vue.set(state.items, index, payload.item)
}
来自:
您不应该使用组件的观察器来监听状态变化。我建议您使用 getter 函数,然后将它们映射到您的组件中。
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters({
myState: 'getMyState'
})
}
}
在您的商店中:
const getters = {
getMyState: state => state.my_state
}
您应该能够通过在您的组件中使用 this.myState 来收听对您的商店所做的任何更改。
https://vuex.vuejs.org/en/getters.html#the-mapgetters-helper
我正在使用带有 Vuex 的 Quasar 将数据集加载到 QTable 中。它工作得很好,但我正在尝试使用 QPopupEdit 来更改项目的状态。数据是从一个Laravel API中拉取的,原始数据集是一个Laravel资源,所以我有项目,每个项目都有一个状态对象(item.status_id和状态:id , 状态:姓名等)
我已经在 q-table 之外公开了第一条记录的状态值,当我将更新推送到 API 时,我 return 更改了项目资源, 将它插入到 vuex mutation 中的 Vuex 数据中,它不会在 table.
中更新<div v-if="items && items[0] && items[0].order">
{{items[0].status.id}} | {{items[0].status.name}}
</div>
<q-table
title="Projects"
:data="items"
:columns="columns"
color="primary"
row-key="id"
:loading="loading"
no-data-label="no projects with search prameters"
:visible-columns="visibleColumns">
<template v-slot:top="props">
<q-btn
flat round dense
:icon="props.inFullscreen ? 'fullscreen_exit' : 'fullscreen'"
@click="props.toggleFullscreen"
class="q-ml-md"
/>
<q-space />
<q-select
v-model="visibleColumns"
multiple
borderless
dense
options-dense
emit-value
map-options
:options="columns"
option-value="name"
style="min-width: 150px"
/>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td key="user" :props="props">
{{ props.row.order.user.firstname }} {{ props.row.order.user.lastname }}
</q-td>
<q-td key="name" :props="props">
{{ props.row.service.name }}
</q-td>
<q-td key="status" :props="props">
<q-badge v-if="props.row.status" :color="props.row.status.color" outline>
{{ props.row.status.name }}
</q-badge>
<q-popup-edit v-model="props.row.status.id" :key="item">
<q-select fill-input color="primary" v-model="props.row.status.id" :key="props.row" :options="statuses" label="Status" emit-value map-options option-label="name" @input="(val) => saveStatus(val, props.row, index)" />
</q-popup-edit>
{{props.row.status.id}} | {{props.row.status_id}}
</q-td>
<q-td key="updated_at" :props="props">
{{ formatDate(props.row.updated_at, 'MMM D, YYYY HH:mm A')}}
</q-td>
<q-td key="notes" :props="props">
<div class="table-description cursor-pointer">
<q-icon v-if="!props.row.notes" name="fal fa-comment-alt" class="float-right" />
{{ props.row.notes }}
<q-popup-edit
buttons
v-model="props.row.notes"
>
<q-input
type="textarea"
v-model="props.row.notes"
autofocus
counter
@keyup.enter.stop
/>
</q-popup-edit>
</div>
</q-td>
<q-td key="id" :props="props">
<q-btn icon="fal fa-arrow-right" :to="'/item/' + props.row.id" class="cursor-pointer" />
</q-td>
</q-tr>
</template>
</q-table>
脚本节选
import { mapState } from 'vuex'
import { date } from 'quasar'
export default {
data () {
return {
inFullscreen: false,
visibleColumns: [ 'user', 'name', 'status', 'updated_at', 'notes', 'id' ],
columns: [
{ name: 'user', align: 'left', label: 'Client', field: row => row.order.user.firstname, format: (val, row) => `${val}`, sortable: false },
{ name: 'name', required: true, label: 'Name', align: 'left', field: row => row.service.name, format: val => `${val}`, sortable: true },
{ name: 'status', align: 'left', label: 'Status', field: row => row.status.name, format: val => `${val}`, sortable: true },
{ name: 'updated_at', align: 'left', label: 'Last Updated', field: row => row.status.updated_at, format: val => `${val}`, sortable: true },
{ name: 'notes', align: 'left', label: 'Notes', field: 'notes', sortable: false },
{ name: 'id', align: 'right', label: 'Actions', field: 'id', sortable: false }
]
}
},
mounted () {
this.fetch()
if (!this.statuses || this.statuses.length < 1) {
this.$store.dispatch('items/fetchStatuses')
}
},
computed: {
...mapState({
loading: state => state.auth.loading,
authuser: state => state.auth.user,
pagination: state => state.items.pagination,
items: state => state.items.items,
statuses: state => state.items.statuses
})
},
methods: {
saveStatus (value, item, index) {
console.log(value + ' | ' + index)
console.log(item)
let payload = { 'status_id': value, 'item_id': item.id, 'index': index }
this.$store.dispatch('items/saveStatus', payload)
},
formatDate (dt, mask) {
return date.formatDate(date.extractDate(dt, 'YYYY-MM-DDTHH:mm:ss.SSSSSSZ'), mask)
},
fetch () {
this.$store.dispatch('auth/statusLoading', true)
this.$store.dispatch('items/fetchItems', this.id).then((res) => {
this.$store.dispatch('auth/statusLoading', false)
}).catch(error => {
if (error) {
console.log(error)
}
})
},
}
}
我的动作和来自 vuex 项目模块的变异
export function saveStatus ({ state, commit, getters }, payload) {
return new Promise((resolve, reject) => {
axiosInstance.post('/api/status/update/Item/' + payload.item_id, payload)
.then(response => {
// alert(JSON.stringify(response, null, 4))
let pl = { 'item': response.data.data }
commit('setIndexItem', pl)
resolve(null)
// console.log(response)
// commit('setItems', response.data.data)
})
.catch(err => {
reject(err)
})
})
}
export function setIndexItem (state, payload) {
var index = state.items.findIndex(i => i.id === payload.item.id)
state.items[index] = payload.item
}
我知道 Laravel API 部分正在工作 - 数据库中的值正在更新,更新状态的项目正在 returned 到 vuex 商店,这就是正在 vuex 存储库中更新,如公开的第一个调试元素所示,但在 QTable 中,它不会更新。
也许 Array Change Detection leads the view not updated. You can use the Vue.set 更新视图
import Vue from 'vue'
// ...
export function setIndexItem (state, payload) {
var index = state.items.findIndex(i => i.id === payload.item.id)
Vue.set(state.items, index, payload.item)
}
来自:
您不应该使用组件的观察器来监听状态变化。我建议您使用 getter 函数,然后将它们映射到您的组件中。
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters({
myState: 'getMyState'
})
}
}
在您的商店中:
const getters = {
getMyState: state => state.my_state
}
您应该能够通过在您的组件中使用 this.myState 来收听对您的商店所做的任何更改。
https://vuex.vuejs.org/en/getters.html#the-mapgetters-helper