У меня проблема с обновлением данных в хранилище Vuex в слегка вложенной структуре данных.
Мой полный проект немного сложнее, чем то, что ниже, но проблема, с которой я сталкиваюсьтеперь упрощен и настроен таким образом, что для каждой страницы проекта будет целевая страница, на которой размещена видимость таблицы , а также отдельный компонент таблицы ,внутри которого есть элемент Vuetify v-data-table, который просто принимает заголовки и элементы как реквизиты и отображает их.Это может быть визуализировано в следующей форме:
- Project Page
|- Landing page
|- Table Visibility
|- Table Component
|- v-data-table
Один из способов обдумать это следующим образом: Для каждого животного (страница проекта) существует три разных породы / типа, каждая из которых имеет свои особенности.Таким образом, вышеупомянутая структура будет иметь вид:
- Dog
|- Landing page
|- Table Visibility
|- German Shepherd
|- v-data-table
|- Bull Terrier
|- v-data-table
|- Labrador Retriever
|- v-data-table
- Cat
|- Landing page
|- Table Visibility
|- Russian Blue
|- v-data-table
|- British Shorthair
|- v-data-table
|- Persian
|- v-data-table
- Bird
|- Landing page
|- Table Visibility
|- Cockatiel
|- v-data-table
|- Parrot
|- v-data-table
|- Macaw
|- v-data-table
Когда пользователь переходит на любую из страниц проекта, он или она будет иметь возможность выбирать с помощью видимость таблицы компонент, какие таблицы будут доступны для просмотра.Этот компонент выглядит примерно так:
TableVisibility.vue ### -> tableTitles теперь извлекается как опора из родительского компонента
<template>
<div>
<v-card>
<v-card-title>
<p class="title ma-0">Table Visibility</p>
</v-card-title>
<v-divider class="mx-5"></v-divider>
<v-card-text>
<v-layout row wrap fill-height>
<v-checkbox
v-for="(title, idx) in tableTitles"
v-model="tableVisibility"
:label="title"
:value="title"
:key="idx"
class="mx-1"
multiple
></v-checkbox>
</v-layout>
</v-card-text>
<v-card-actions>
<v-switch
v-model="showAll"
:label="showAll ? 'Hide All' : 'Show All'"
></v-switch>
<v-spacer></v-spacer>
</v-card-actions>
</v-card>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: "TableChoices",
props: ['tableTitles'],
data() {
return {
showAll: false,
displayTables: [],
}
},
methods: {
},
computed: {
...mapState({
pageName: state => state.pageName,
}),
},
watch: {
showAll(bool) {
bool ?
this.displayTables = this.tableTitles :
this.displayTables = []
},
displayTables: {
handler() {
let tableObj = {};
this.tableTitles.forEach(title => { tableObj[title] = this.displayTables.indexOf(title) > -1 })
this.$store.commit('setTableVisibility', {page: this.pageName, tables: tableObj})
if (this.displayTables.length === this.tableTitles.length) {
this.showAll = true
} else if (this.displayTables.length === 0) {
this.showAll = false
}
}
},
}
}
</script>
<style scoped>
</style>
LandingPage.vue
<template>
<div>
</div>
</template>
<script>
import Dog from '@/components/Dog'
import Cat from '@/components/Cat'
import Bird from '@/components/Bird'
import { mapState, mapGetters } from 'vuex'
export default {
name: "LandingPage",
components: {
Dog,
Cat,
Bird,
},
data() {
return {
items: {},
headers: {},
}
},
computed: {
...mapState({
pageName: state => state.pageName,
}),
...mapGetters({
tableVisibility: 'getTableVisibility'
})
},
watch: {
tableVisibility: {
handler() { console.log('tableVisibility in LandingPage.vue', this.tableVisibility)},
deep: true
},
}
}
</script>
<style scoped>
</style>
Нет смысла устанавливать компоненты Dog, Cat или Bird, потому что единственное, что у них есть, - это таблица данных Vuetify, так что они могут быть просто заполнителями, поскольку они не важны.
Хранилищенастроить так:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const debug = process.env.NODE_ENV !== 'production'
function initialState() {
return {
pageItems: {},
pageHeaders: {},
pageName: '',
tableTitles: {
Dog: ['German Shepherd', 'Bull Terrier', 'Labrador Retriever'],
Cat: ['Russian Blue', 'British Shorthair', 'Persian'],
Bird: ['Cockatiel', 'Parrot', 'Macaw']
},
tableVisibility: {
Dog: {
German Shepherd: false,
Bull Terrier: false,
Labrador Retriever: false
},
Cat: {
Russian Blue: false,
British Shorthair: false,
Persian: false
},
Bird: {
Cockatiel: false,
Parrot: false,
Macaw: false
}
}
}
}
const state = {...initialState()}
const mutations = {
setTableVisbility(state, payload) {
const page = payload.page;
const tables = payload.tables;
// Vue.set(state.tableVisibility, page, tables)
state.tableVisibility[page] = Object.assign({}, tables);
}
}
const getters = {
getTableVisibility: (state) => ( state.tableVisibility[state.PageName] ),
getCurrentPageTableTitles: (state) => ( state.tableTitles[state.pageName] ),
}
export default new Vuex.Store({state, mutations, getters, strict: debug})
Как я уже сказал, весь проект более сложный, чем этот (функциональность магазина, которую я здесь показываю, фактически находится в модуле и т. д.), но у меня возникают проблемы дажеполучение обновленного значения tableVisibility в компоненте LandingPage.vue.Я пробую несколько различных способов применения обработчика deep к наблюдателю (https://vuejs.org/v2/api/#watch и https://medium.com/@stijlbreuk/six-random-issues-and-their-solutions-in-vuejs-b16d470a6462);. Я попытался разделить функциональность массива в хранилище с помощьюочистка массива с помощью сплайсинга ( Как очистить массив в JavaScript? ), а затем вставка всех элементов обратно в массив; я попытался использовать метод массива filter , чтобы попытатьсясоздать новый массив; я попытался сохранить tableVisibility как объект (с именем таблицы в качестве ключа и значением как true или false), чтобы я мог использовать Object.assign (https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats);нашел эту страницу о нормализации данных (https://forum.vuejs.org/t/vuex-best-practices-for-complex-objects/10143/2),, но кажется, что это не очень сложно до такой степени, что это уже довольно просто.
Я нахожусь в конце своего ума, пытаясь выяснить,что происходит, и я очень признателен за помощь.
Редактировать
Я обновил проект, включив в него геттеры, и реактивность работает во всех других компонентах, кроме значения tableVisibility. I 'мы пытались оставить элементы tableVisibility в виде массивов, затем я попытался преобразовать их в объекты, как видно из этого редактирования, и я попытался использовать Vue.set для обновления значений, что не сработало, затем я попытался использовать Object.assign как естьпоказано в этой текущей версии.Если я отошел от страницы, а затем вернулся, значения обновились, просто они, похоже, теряли реактивность, несмотря на мои попытки использовать Vue.set и Object.assign.