Vue.jsのprovide/injectの使い方!【解説とサンプルコード】

Vue.js Vue.js

Vue.jsのprovideとinjectの使い方について書いています。
公式ドキュメントのこの辺の内容になります。

紹介しているサンプルコードは下記のバージョンで検証しました。

Vue.js 3.0.0 (Compotision API)
Vue CLI 4.5.0

Vue.jsのprovideとinjectについて

Vue.jsでコンポーネント間のデータ受け渡しをするときには、propsを使用するのが基本かと思います。
provideとinjectを使用すると、子のコンポーネントだけでなく、全ての子コンポーネントでデータが共有できるようになります。

赤枠の親コンポーネントでprovideを使用して、値を保持すると、配下の青枠の子コンポーネント全てで取得可能です。
Vue.jsのprovide/injectの図

provideの使い方

provideを使用すると、任意の値をキー文字列と一緒に保持することができます。

provideをimportして、プログラムの任意の場所で使用します。
例えば、下記のように使うことが可能です。

import { provide, ref } from 'vue'

export default ({
  setup() {
    const userName = ref('')
    provide('inputUserName', userName)
  }
})

上記ではuserNameをrefでリアクティブな変数として定義した後に、provideに渡しています。
provideの左側がキー名になり、右側が共有したい値になります。

今回はrefで定義した変数を入れましたが、文字列や配列など、いろいろな内容を保持することができます。

provide('helloText', 'hello world')
provide('fruitArray', ['apple', 'grape', 'orange', 'banana'])

injectの使い方

injectを使用すると、provideで保持された値をキー文字列を使用して取得することができます。
上記で保持したデータを取得する場合は、下記のようにして取得することができます。

import { inject } from "vue";

export default ({
  setup() {
    const userName = inject('inputUserName')

    return {
      userName,
    }
  }
})

injectをimportして、プログラムの任意の場所で使用します。
injectに渡している文字列は、値をprovideに渡した時のキー文字列です。

これで渡した値を取り出すことが可能です。
キー文字列の値がない場合は、undefinedが返ってきます。

provide/injectを使用したサンプルコード

実際にprovideとinjectを使用したサンプルコードを書いてみました。
ユーザーの情報(名前・年齢・住所)を入力して、表示させるだけのコンポーネントになります。

provideとinjectの機能を確認するために、3つのコンポーネントを用意してみました。

コンポーネント 役割
UserInputCard.vue ユーザー情報を入力するコンポーネント
ShowUserInformationを呼び出す。
ShowUserInformation.vue ユーザー情報を表示する枠のみを提供
ShowUserInformationDataを呼び出す
ShowUserInformationData.vue ユーザー情報を表示する

UserInputCardで入力した内容をprovideを使用して保持します。
そして、2つ下のShowUserInformationDataコンポーネントでinjectを使って取得し、表示してみます。

コンポーネントの呼び出し順としては
UserInputCard => ShowUserInformation => ShowUserInformationData となります。
Vue.jsでprovideとinjectの検証用コンポーネント構成

入力した内容をprovideで保持するコンポーネント

まず、UserInputCard.vueのコードになります。

<template>
  <div class="border-2 border-blue-300 rounded w-4/12 p-3 m-3">
    <table>
      <tr>
        <td>ユーザー名</td><td><input type="text" v-model="userName" class="ml-1 border border-gray-400 rounded p-2" /></td>
      </tr>
      <tr>
        <td>年齢</td><td><input type="text" v-model="userAge" class="ml-1 border border-gray-400 rounded p-2" /></td>
      </tr>
      <tr>
        <td>住所</td><td><input type="text" v-model="userAddress" class="ml-1 border border-gray-400 rounded p-2" /></td>
      </tr>
    </table>
    <show-user-information />
  </div>
</template>
<script>
import { provide, ref } from 'vue'
import ShowUserInformation from './ShowUserInformation.vue'

export default ({
  components: {
    ShowUserInformation
  },
  setup() {
    const userName = ref('')
    const userAge = ref('')
    const userAddress = ref('')

    provide('inputUserName', userName)
    provide('inputUserAge', userAge)
    provide('inputUserAddress', userAddress)

    return {
      userName,
      userAge,
      userAddress
    }
  }
})
</script>

タグの箇所を確認します。
3つのテキストボックスを用意しています。
それぞれにv-modelを使用して、作成したリアクティブな変数を関連付けています。

<input type="text" v-model="userName" class="ml-1 border border-gray-400 rounded p-2" />
<input type="text" v-model="userAge" class="ml-1 border border-gray-400 rounded p-2" />
<input type="text" v-model="userAddress" class="ml-1 border border-gray-400 rounded p-2" />

次にスクリプトの箇所を確認します。
まず、provideとrefをimportで読み込んでいます。

refを使用して、テキストボックスに関連づけるためのリアクティブな変数を3つ作成しています。
その後に、作成した変数をprovideしています。

provide('inputUserName', userName)
provide('inputUserAge', userAge)
provide('inputUserAddress', userAddress)

これで、「inputUserName」・「inputUserAge」・「inputUserAddress」というキー名で、それぞれの変数が保持されます。
リアクティブな状態なので、テキストボックスの内容が変えられると保持されている内容や取得した内容も変わります。

枠のみを提供するコンポーネント

次にShowUserInformation.vueのコードになります。

このコンポーネントでは、データ表示するコンポーネントを呼び出しているだけです。
黄色の枠のみを表示して、ShowUserInformationDataコンポーネントを呼んでいます。

<template>
  <div class="border-2 border-yellow-300 rounded mt-3">
    <show-user-information-data />
  </div>
</template>
<script>
import ShowUserInformationData from './ShowUserInformationData.vue'

export default ({
  components: {
    ShowUserInformationData
  },
})
</script>

injectで取り出した情報を表示するコンポーネント

最後にShowUserInformationData.vueのコードです。

<template>
  <div class="border-2 border-yellow-100 p-2">
    入力したユーザー名: {{ userName }}
  </div>
  <div class="border-2 border-yellow-100 p-2">
    入力した年齢: {{ userAge }}
  </div>
  <div class="border-2 border-yellow-100 p-2">
    入力した住所: {{ userAddress }}
  </div>
</template>
<script>
import { inject } from "vue";

export default ({
  setup() {
    const userName = inject('inputUserName')
    const userAge = inject('inputUserAge')
    const userAddress = inject('inputUserAddress')

    return {
      userName,
      userAge,
      userAddress,
    }
  }
})
</script>

タグの方を確認します。
userNameuserAgeuserAddressの3つの変数を表示しているだけです。

次にスクリプトです。
importでinjectを呼び出しています。

injectを使用して、下記のように、それぞれ親のコンポーネントで入力された内容を取り出しています。

const userName = inject('inputUserName')
const userAge = inject('inputUserAge')
const userAddress = inject('inputUserAddress')

そして、最後にreturnして画面に表示しているという形になります。

動作確認する

作成したサンプルコードをブラウザを開いて確認すると、下記のようになりました。
Vue.jsのprovideとinjectを確認する

入力した内容がprovideに保持されて、孫コンポーネントからinjectで呼び出されて取り出されていることが確認できました。

終わりに

今回はVue.jsのprovideとinjectを使ってみました。
作成した親コンポーネントでprovideした値を、孫コンポーネントからinjectして取り出せることが確認できました。

コメント

タイトルとURLをコピーしました