同じコンポーネントでStoreを使って状態を共有できるか確かめてみた話[Vue]

#はじめに
兄弟コンポーネント間での値のやり取りには**Vuex**や**自作のstore**を使えば、`props`と`emit`でバケツリレーをせずにやることが可能です。
ふと疑問に思ったのが同じコンポーネントを複数使い回して、その間で**store**を使えば状態の共有ができるのか？でした。
疑問に思ったらやってみよう！ということでやったみたのが今回の記事となります。
#実験
##まずは準備
今回使うコンポーネントとstoreモジュールを作っていきましょう。
最初に**Store**の方から作っていきましょう。

```javascript:store.js
export const Store = {
  state: {
    StoreValue: "Qiita"
  },
  setStore(value) {
    this.state.StoreValue= value;
  },
  getStore(){
    return this.state.StoreValue;
  }
};
```
状態を持つのは**state**の部分で、実際に状態を取得したり設定したりするのも**store**にアクションを作っています。

次にVueのコンポーネントを作っていきます。
まずは**HTML**部分からです。

```vuejs:component.vue
<template>
  <div>
    <p>{{ ComponentValue }}</p>
    <button @click="onButtomClick">Click</button>
  </div>
</template>
```
結果を表示するための**P**タグと、イベントを発火するための**Button**タグを配置しました。
次に**Script**部分。

```javascript:component.vue
<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>
```
全体としてはこのような感じになりました。
重要そうなとこを細かく見ていきましょう。

```javascript:component.vue
  data() {
    return {
      StoreObject: Store.state,
    };
  },
```
**data**オブジェクトで、読み込んだ**Store**の状態を持たせています。
ここで**Store**をもたせておかないと、うまく更新されたものを反映できませんでした。

```javascript:component.vue
  computed: {
    ComponentValue: {
      set(value) {
        Store.setStore(value);
      },
      get() {
        return Store.getStore();
      }
    }
  }
```
算出プロパティのほうは**getter/setter**で**store**に対して状態を取得と設定を行うようにしています。

```javascript:component.vue
  methods: {
    onButtomClick(value) {
      this.ComponentValue = `${this.ComponentValue}！`;
    }
  }
```
ボタンをクリックした時に行うメソッドです。
算出プロパティを介して**store**の値を取得し、それを！マークと文字列結合をして、再度**store**のアクションで状態を設定しにいく。
という流れになっています。

あとは親のほうで、作ったコンポーネントを複数配置すれば完了です。


```vuejs:component.vue
<template>
  <div>
    <qiita></qiita>
    <qiita></qiita>
  </div>
</template>
```
##やってみた
![ezgif-3-f54e35782a1d.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257615/690fc262-192c-7928-3c95-515ef24118b0.gif)

実際に動かしてみると、クリックしていないほうのも！マークが増えているので、同じコンポーネントでも**store**を介して状態を共有できることがわかりました。

本当に**store**を介してるのか？
ただたんに同じコンポーネントだから状態が共有されてるだけなのでは？という疑問もあったので、
**data**のインスタンス変数を使った場合にどうなるかというのをやってみましょう。

###インスタンス変数に変えてみる
```javascript:component.vue
  data() {
    return {
      StoreObject: Store.state,
      childvalue:"Vue"
    };
  },
```
```javascript:component.vue
  computed: {
    ComponentValue: {
      set(value) {
        // Store.setStore(value);
        this.childvalue= value;
      },
      get() {
        // return Store.getStore();
        return this.childvalue;
      }
    }
  }
```
**data**にインスタンス変数を追加し、算出プロパティでのgetter/setterもそちらに対しての処理を行うように変更します。
この状態でどのように動くかを見てみましょう。

![ezgif-3-3a6877c3dc30.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257615/5c69d892-886e-eff7-b7d7-db1186842b49.gif)

連動しなくなりました。
ということは、同じコンポーネントを使い回していても、コンポーネントはそれぞれ独立したインスタンスになっている、ということがわかります。
なので、上のほうのでは**store**を介して状態が共有されている、と言えますね！

#まとめ

同じコンポーネントでも**store**を使えば状態を共有できることが解りました。
ただしこれを使うシチュエーション自体がかなり限られてきますが、これを知っておくと似た構成のコンポーネントを増やして対応…
というのがなくなるかと思います！