I'm not sure I grasp all the details of your requirements, but understand data is common across multiple 'pages' in the SPA.
I would definitely recommend Vuex:
- same data for all pages
- access via component computed properties,
which are reactive to store changes but also cached to save
recomputing if no changes in dependencies
- saves a lot of potentially complex passing of data in props (passing downwards) and events (passing upwards)
Looking at the pseudocode, you have three types of filters on the sidebar. Put that data in the store as well, then computed properties on views can apply filters to the data. Computation logic is then easily tested in isolation.
child.vue
<template>
<div>{{ myChildData.someProperty }}</div>
</template>
<script>
export default {
props: [...],
data: function () {
return {
selection: 'someValue' // set this by, e.g, click on template
}
},
computed: {
myChildData() {
return this.$store.getters.filteredData(this.selection)
}
}
}
</script>
store.js
const state = {
myData: {
...
},
filters: { // set by dispatch from sidebar component
keyword: ...,
toggle: ...,
range: ...
},
}
const getters = {
filteredData: state => {
return childSelection => { // this extra layer allows param to be passed
return state.myData
.filter(item => item.someProp === state.filters.keyword)
.filter(item => item.anotherProp === childSelection)
}
},
}
const mutations = {
'SET_DATA' (state, payload) {
...
},
'SET_FILTER' (state, payload) {
...
}
}
export default {
state,
getters,
mutations,
}
Generic children
There are probably many ways to tackle this. I've used composition, which means a thin component for each child each using a common component, but you only need this if the child has specific data or some unique markup which can be put into a slot.
child1.vue
<template>
<page-common :childtype="childType">
<button class="this-childs-button" slot="buttons"></button>
</page-common>
</template>
<script>
import PageCommon from './page-common.vue'
export default {
props: [...],
data: function () {
return {
childType: 'someType'
}
},
components: {
'page-common': PageCommon,
}
}
</script>
page-common.vue
<template>
...
<slot name="buttons"></slot>
</template>
<script>
export default {
props: [
'childtype'
],
data: function () {
return {
...
}
},
}
</script>
Multiple Instances of Data
Again, many variations - I used an object with properties as index, so store becomes
store.js
const state = {
myData: {
page1: ..., // be sure to explicitly name the pages here
page2: ..., // otherwise Vuex cannot make them reactive
page3: ...,
},
filters: { // set by dispatch from sidebar component
keyword: ...,
toggle: ...,
range: ...
},
}
const getters = {
filteredData: state => {
return page, childSelection => { // this extra layer allows param to be passed
return state.myData[page] // sub-select the data required
.filter(item => item.someProp === state.filters.keyword)
.filter(item => item.anotherProp === childSelection)
}
},
}
const mutations = {
'SET_DATA' (state, payload) {
state.myData[payload.page] = payload.myData
},
'SET_FILTER' (state, payload) {
...
}
}
export default {
state,
getters,
mutations,
}