背景と目的
コンポーネントのネストが深い場合、propsとemitを使う方法だと冗長になるため、これまではデータストアを経由してデータのやり取りをすることが多かったが、データの内容が薄く、単純であることや、特定のコンポーネント構成でしか使用しないデータだったのでprovideとinjectを使った実装をすることにした。
実装内容
まずは親コンポーネント
<template>
<div>
<ChildComponent />
</div>
</template>
<script setup>
// 子コンポーネントと共有したいデータ
const data = ref(
{
status : false,
steps:[],
}
);
// provideして子孫が参照できるようにする
provide('parentData',data);
</script>
通常通りデータを定義し、それをprovideで名前をつけておくだけ。
続いて子コンポーネント
<template>
<p>{{ parentData.status === true ? '公開' : '非公開'}}</p>
</template>
<script setup>
const parentData = inject('parentData');
</script>
injectで名前を指定して呼び出して使うだけ。
この例では親と子しか無いが、さらに孫、曾孫とコンポーネントのネストが深くなっても親子関係にある限りはinjectを使ってデータを参照することができる
データストアとの違い
個人的にはデータストアの方がデータやそれに関する処理を分離できるので、特に理由がなければデータストアで十分だと思う。
provideとinjectを使う場合、injectを使うコンポーネントは必ずprovideしているコンポーネントの配下に入らないといけないため、コンポーネント間の結合度が高まるのもマイナスポイント。
そのため、下記のような基準で判断するといいと思う。
ネスト | 親子関係 | データの複雑さ | |
---|---|---|---|
props/emit | 親と子だけ | 親子関係が必要 | 簡単 |
provide/inject | 3階層以上 | 親子関係が必要 | 簡単 |
データストア | ネストの深さに関係ない | 親子関係が必要でない | 複雑 |
リンク
以前書いた記事で棲み分けについて話してます