はじめに
兄弟コンポーネント間での値のやり取りにはVuexや自作のstoreを使えば、props
とemit
でバケツリレーをせずにやることが可能です。
ふと疑問に思ったのが同じコンポーネントを複数使い回して、その間でstoreを使えば状態の共有ができるのか?でした。
疑問に思ったらやってみよう!ということでやったみたのが今回の記事となります。
実験
まずは準備
今回使うコンポーネントとstoreモジュールを作っていきましょう。
最初にStoreの方から作っていきましょう。
export const Store = {
state: {
StoreValue: "Qiita"
},
setStore(value) {
this.state.StoreValue= value;
},
getStore(){
return this.state.StoreValue;
}
};
状態を持つのはstateの部分で、実際に状態を取得したり設定したりするのもstoreにアクションを作っています。
次にVueのコンポーネントを作っていきます。
まずはHTML部分からです。
<template>
<div>
<p>{{ ComponentValue }}</p>
<button @click="onButtomClick">Click</button>
</div>
</template>
結果を表示するためのPタグと、イベントを発火するためのButtonタグを配置しました。
次にScript部分。
<script>
import { Store } from "./store.js";
export default {
data() {
return {
StoreObject: Store.state,
};
},
computed: {
ComponentValue: {
set(value) {
Store.setStore(value);
},
get() {
return Store.getStore();
}
}
},
methods: {
onButtomClick(value) {
this.ComponentValue = `${this.ComponentValue}!`;
}
}
};
</script>
全体としてはこのような感じになりました。
重要そうなとこを細かく見ていきましょう。
data() {
return {
StoreObject: Store.state,
};
},
dataオブジェクトで、読み込んだStoreの状態を持たせています。
ここでStoreをもたせておかないと、うまく更新されたものを反映できませんでした。
computed: {
ComponentValue: {
set(value) {
Store.setStore(value);
},
get() {
return Store.getStore();
}
}
}
算出プロパティのほうはgetter/setterでstoreに対して状態を取得と設定を行うようにしています。
methods: {
onButtomClick(value) {
this.ComponentValue = `${this.ComponentValue}!`;
}
}
ボタンをクリックした時に行うメソッドです。
算出プロパティを介してstoreの値を取得し、それを!マークと文字列結合をして、再度storeのアクションで状態を設定しにいく。
という流れになっています。
あとは親のほうで、作ったコンポーネントを複数配置すれば完了です。
<template>
<div>
<qiita></qiita>
<qiita></qiita>
</div>
</template>
やってみた
実際に動かしてみると、クリックしていないほうのも!マークが増えているので、同じコンポーネントでもstoreを介して状態を共有できることがわかりました。
本当にstoreを介してるのか?
ただたんに同じコンポーネントだから状態が共有されてるだけなのでは?という疑問もあったので、
dataのインスタンス変数を使った場合にどうなるかというのをやってみましょう。
インスタンス変数に変えてみる
data() {
return {
StoreObject: Store.state,
childvalue:"Vue"
};
},
computed: {
ComponentValue: {
set(value) {
// Store.setStore(value);
this.childvalue= value;
},
get() {
// return Store.getStore();
return this.childvalue;
}
}
}
dataにインスタンス変数を追加し、算出プロパティでのgetter/setterもそちらに対しての処理を行うように変更します。
この状態でどのように動くかを見てみましょう。
連動しなくなりました。
ということは、同じコンポーネントを使い回していても、コンポーネントはそれぞれ独立したインスタンスになっている、ということがわかります。
なので、上のほうのではstoreを介して状態が共有されている、と言えますね!
まとめ
同じコンポーネントでもstoreを使えば状態を共有できることが解りました。
ただしこれを使うシチュエーション自体がかなり限られてきますが、これを知っておくと似た構成のコンポーネントを増やして対応…
というのがなくなるかと思います!