Home > Blockchain >  Isolated stores for each root component
Isolated stores for each root component

Time:07-06

I have a project where i need to use a store to manage a root component with many child components, now i need to make copies of that root component with different props values, but the state is shared across the entire app, is there a way to scope the store it to root component?

example to illustrate the problem:

App.vue

<script>
import ComponentA from './components/ComponentA.vue'
</script>
<template>
  <ComponentA name="comp1"/>
  <ComponentA name="comp2"/>
  <ComponentA name="comp3"/>
</template>

ComponentA.vue

<script>
import { store } from './store.js'
export default{
  props: ["name"],
  data(){
    return { store }
  }
}
</script>
<template>
{{name}}:{{store.count}}
<button @click="store.increment()">increment</button>
</template>

store.js

import { reactive } from 'vue'
export const store = reactive({
  count: 0,
  increment(){
    this.count  
  }
})

CodePudding user response:

I don't think that's possible without some sort of refactor.

The global store is helpful if you don't want to deal with prop drilling (and event emitting), but in order to scope it, the component ant its children will need to know which store to use. I think the easiest way to implement that would be to make use of provide/inject. You can use provide/inject to share a store instance

import { reactive } from 'vue'
export function createStoreInstance() {
  return reactive({
    count: 0,
    increment(){
      this.count  
    }
  })
}

then, in your component you would generate the instance during creation

<script>
import { createStoreInstance } from './store.js'

export default {
  components: {
    GrandChild
  },
  provide() {
    return {
      store: this.store
    }
  },
  beforeCreate(){
    this.store = createStoreInstance()
  },
  methods:{
    increment(){
      this.store.count   
    }
  }
}
</script>

and in the child component just get the store

<script>
export default {
  inject: [ 'store']
}
</script>

<template>
  <p>
    {{store}}
  </p>
</template>

here is a SFC playground link

You can also use a global store that would accommodate keyed instances, and then use provide inject to pass the key to the children, but I think that would make the store more complicated, but there might be use cases where that may be a better approach (like if you want to be able to save the store state)

  • Related