うしろのこの本ください

なんでもかきます

Vue3のinject/provideでミニマルなストアを作る

ストアの型はサボった。 github.com

Vue3からinjectprovideという関数が提供されており、(機能的にはVue2のものと同じだが)コンポネ間の状態共有が簡単にできるようになった。

ドキュメント https://composition-api.vuejs.org/api.html#dependency-injection

簡単に言うと、provideにキー付きで渡したリアクティブな状態をinjectで取り出すことでどこからでも状態を参照できるようになるもの。

provideinjectsetupでのみ動作する。

例えば状態を共有したいコンポーネント2つがあった時、それ用のスコープでディレクトリを切って専用のストアを作ることが可能。 Symbolを使って一意のキーを生成し、リアクティブにしたい状態や関数をセットでprovideに渡す。

components/miniStore/index.ts

import { ref, inject, provide } from 'vue'

export const key = Symbol()

export const createStore = () => {
  const count = ref(0)
  const increment = () => count.value++

  return {
    count,
    increment,
  }
}

export const provideStore = () => {
  provide(key, createStore())
}

export const useStore = (): any => {
  return inject(key)
}

コンポネではexportされたuseStoresetupで呼び出して、使いたい値を取り出すだけ。

カウントアップする側 index.vue

<script lang="ts">
import { defineComponent } from 'vue'
import { useStore } from './miniStore'

export default defineComponent({
  setup() {
    const { increment } = useStore()
    return {
      increment
    }
  }
})
</script>

<template>
  <button @click="increment">increment</button>
</template>

カウント出す側 sub.vue

<script lang="ts">
import { defineComponent } from 'vue'
import { useStore } from './miniStore'

export default defineComponent({
  setup() {
    const { count } = useStore()
    return {
      count
    }
  }
})
</script>

<template>
  <div>{{ count }}</div>
</template>

アプリケーションのエントリーポイント等でminiStoreからproviderを呼び出し登録をする。

App.vue

<script lang="ts">
import { defineComponent } from 'vue'
import { provideStore } from './components/miniStore'
import Index from './components/index.vue'
import Sub from './components/sub.vue'

export default defineComponent({
  components: {
    Index,
    Sub,
  },
  setup() {
    provideStore()
  }
})
</script>

<template>
  <div>
    <Sub />
    <Index />
  </div>
</template>

動きます。

f:id:apple19940820:20200529214133g:plain

おわり

Vuexを使わなくてもコンポーネント間で状態の共有が簡単にできるため、ユースケースによってはこれで事足りるかもしれない。Vue 3からこういう便利関数みたいなのが沢山exportされているので結構遊べそうな雰囲気。特に@vue/reactivity周り。