Vuex状態マシンの迅速な理解と実例の応用


一.速識概念:
1.コンポーネント間でデータを共有する方式:
通常は次のような方法があります。
  • 父から子への値:v-bind属性バインディング;
  • 子は親に値を伝えます。v-onイベントバインディング。
  • 兄弟構成要素間でデータを共有する:EventBus;
  • 2.vuexとは何ですか
  • 公式の話によると、VuexはVue.jsアプリケーションのために開発された状態管理モードである。集中的なストレージ管理アプリケーションのすべてのコンポーネントの状態を採用し、対応する規則的な保証状態で予測可能な方法で変化する。VuexはVueの公式デバッグツールdevtools extensionにも集積されており、ゼロ構成のようなtime-travelデバッグ、状態スナップショット導入導出などの高級デバッグ機能を提供しています。
  • は簡単に言えば、Vuexはコンポーネントのグローバル状態(データ)管理を実現するメカニズムであり、コンポーネント間のデータの共有を容易に行うことができる。
  • 3.vuexを使うメリット:
  • は、vuexにおいて共有データを集中的に管理することができ、開発と後期メンテナンスが容易である。
  • は、コンポーネント間のデータ共有を効率的に実現し、開発効率を向上させることができる。
  • は、vuexに格納されているデータはすべて応答的であり、データとページとの同期をリアルタイムに維持することができる。
  • は、非親子コンポーネントのメッセージ伝達(stateにデータを格納する)を解決する。
  • は、AJAX要求回数を減少させ、メモリから直接にstateを取得できる場合があります。
  •   一般的には、コンポーネント間で共有されるデータだけが、vuexに格納される必要がある。コンポーネントの私有データについては、不要です。コンポーネント自体のdataに格納すればいいです。もちろん、あなたが望むならば、すべてvuexの中に存在してもいいです。
    二.基本使用:
    1.依存パッケージのインストール:
    
    npm install vuex --save
    
    2.依存パッケージをインポート:
    
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    3.storeオブジェクトを作成する:
    
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
    //state             
      state: {
        count: 0
      }
    })
    
    4.storeオブジェクトをvueインスタンスにマウントする:
    
    new Vue({
      el: '#app',
      store
    })
    
    この時、すべてのコンポーネントはstoreからデータを取得することができます。
    三.作成項目:
    次はvueプロジェクトのプロセスを作成するために、次のケースがあります。
    (1)cmdウィンドウを開けて、vueの可視化パネルを入力してください。

    (2)新規プロジェクトのパスを選択:

    (3)名前:

    (4)手動で設定を選択して、注意するのはvue 2バージョンです。


    (5)作成:

    (6)次のステップ:

    (7)作成に成功し、対応するディレクトリにvscodeを開いてプログラムを開始する:

    (8)運転項目:

    四.説明の前提:
    前提(注意):
      はカウンターの小さい判例を書いて、実例の中から概念に協力してもっと速くvuexを手に入れることができます。したがって、以下のコア概念におけるコード部分をこの小さな事例に基づいて実証した。ターゲット:2つのサブコンポーネントを書いて、共通のcount値があります。親のコンポーネントの中で、一つはクリックした後にcount値を1減らすことができます。一つのコンポーネントはクリックした後にcount値を1増加します。
    親コンポーネントApp.vue初期コード:
    
    <template>
      <div id="app">
           <my-add></my-add>
           <p>--------------------</p>
           <my-reduce></my-reduce>
      </div>
    </template>
    
    <script>
    //     
    import Add from './components/Add.vue'
    import Reduce from './components/Reduce.vue'
    export default {
      name: 'App',
      data() {
        return {
          
        }
      },
      components: {
        'my-add': Add,
        'my-reduce': Reduce
      }
    
    }
    </script>
    
    サブアセンブリAdd.vueの初期コード:
    
    <template>
        <div>
            <p>count  :</p>
               <button>+1</button>
        </div>
     
    </template>
    <script>
      export default{
          data() {
              return {
                  
              }
          },
      }
    </script>
    
    サブコンポーネントReduce.vue初期コード:
    
    <template>
        <div>
             <p>count  :</p>
               <button>-1</button>
        </div>
    </template>
    <script>
      export default{
          data() {
              return {
                  
              }
          },
      }
    </script>
    
    storeオブジェクトの初期コードは以下の通りです。
    
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        count: 0
      }
    })
    
    初期効果:

    五.核心概念:
    1.state:
      オフィシャルの話によると、Vuexは単一状態ツリーを使用しています。ここでは「唯一のデータソース(SSOT)」として存在する。これはまた、各アプリケーションが単にstoreのインスタンスを含むことを意味する。
    簡単に言えば、Stateは唯一の公共データソースを提供し、共有データはStoreのStateにまとめて保存します。
    1.1コンポーネントの中でstateにアクセスする第一の方式:
    コンポーネントに直接以下のコマンドを入力します。
    this.$store.state.参照するデータ名
    Add.vueサブアセンブリで参照するように、
    
    <template>
        <div>
            <p>count  :{{this.$store.state.count}}</p>
               <button>+1</button>
        </div> 
    </template>
    //              ,     
    
    効果を見ると、countの値は0です。

    1.2コンポーネントでstateにアクセスする第二の方式:
    (1)vuexから必要に応じてmapState関数を導入する
    
    import { mapState } from 'vuex'
    
    (2)先ほど導入したmapState関数により、現在のコンポーネントに必要なグローバルデータを、現在のコンポーネントにマッピングしたcomputed計算属性:
    
    computed: {
       ...mapState([count])
    }
    
    豆知識:computtedは自分で定義した変数を監視します。この変数はdataの中で宣言しないで、直接にcomputtedの中で定義して、それからページの上で双方向のデータを行って結合して結果を展示します。あるいは他の処理に使います。
    Reduce.vueサブコンポーネントに引用されるように、
    
    <template>
        <div>
             <p>count  :{{count}}</p>
               <button>-1</button>
        </div>
    </template>
    <script>
    import {mapState} from 'vuex'
      export default{
          data() {
              return {
                  
              }
          },
          computed: {
             ...mapState(['count'])
          }
      }
    </script>
    
    効果を見ても、countの値は0です。

    2.mutation:
      オフィシャルの話によると、Vuexのstoreの状態を変更する唯一の方法はmutationを提出することです。Vuexのmutationは非常にイベントに似ています。各mutationには文字列のイベントタイプと一つのコールバック関数があります。このコールバック関数は私たちが実際に状態変更を行うところで、最初のパラメータとしてstateを受け取ります。
      は簡単に言って、Storeのデータを変更するためのMutationです。
    ①Storeデータはmutationでしか変更できません。Storeのデータは直接操作できません。
    ②このように操作するとやや煩わしいですが、全てのデータの変化を集中的に監視することができます。
    例えば、count値の自己増加1を実現する操作は、先にmotationsで自己増加1の関数を定義します。その後、対応するサブコンポーネントが使いたいのですが、このコンポーネントは直接mutationに導入して、対応する関数を呼び出すといいです。
    以下のように、Add.vueサブアセンブリは、自己増加1機能を実現する。
    まず状態マシンのmuttionsで自己増加を実現できる関数addを定義します。
    
    export default new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        //   1  
        add(state){
          state.count++
        }
      }
    })
    
    2.1 mutationをトリガする第一の方式:
    Add.vueサブコンポーネントにボタンをバインドしてイベントをクリックし、mutationを起動します。
    
    <template>
        <div>
            <p>count  :{{this.$store.state.count}}</p>
               <button @click="btnAdd">+1</button>
        </div>
     
    </template>
    <script>
      export default{
          data() {
              return {
                  
              }
          },
          methods: {
              btnAdd() {
                  //      mutation   ,  add  
                  this.$store.commit('add')
              }
          }
      }
    </script>
    
    効果を見るとクリックしてから増加します。

    2.2トリガmutationとパラメータの転送:
    もちろん、コンポーネントの中でmutationの関数を呼び出す時もパラメータを伝えることができます。
    例えば、自己増加関数がありますが、呼び出し時に入ってきたパラメータをどれだけ増やしたらいいですか?
    
    export default new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        //     ,      state,         
        //    n    
        addN(state,n){
          state.count+= n
        }
      }
    })
    
    対応するコンポーネントの呼び出し時にパラメータを入力します。
    
      methods: {
              btnAdd2() {
                  //   mutation   ,  addN  
                  //    ,   6 
                  this.$store.commit('addN',6)
              }
          }
    
    2.1ムーテートをトリガする第二の方式:
    (1)vuexから必要に応じてmapMuttions関数を導入する
    
    import { mapMutations } from 'vuex'
    
    (2)先ほど導入したmapMuttions関数により、必要なmuttions関数を、現在のコンポーネントのmethods方法にマッピングする。
    
    methods: {
       ...mapMutations(['add','addN'])
    }
    
    実戦で、Reduce.vueコンポーネントのクリック自減1の機能要求を実現する:
    ステータスマシンにマイナス関数を追加します。
    
    export default new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        //   1  
        add(state){
          state.count++
        },
        //   1   
        sub(state){
          state.count--
        }
      }
    })
    
    Reduce.vueコンポーネントはボタンをクリックしてマイナス1を実現します。
    
    <template>
        <div>
             <p>count  :{{count}}</p>
               <button @click="btnSub">-1</button>
        </div>
    </template>
    <script>
    //  
    import {mapState,mapMutations} from 'vuex'
      export default{
          data() {
              return {
                  
              }
          },
          computed: {
             ...mapState(['count'])
          },
          methods: {
              //   mutation  sub  
              ...mapMutations(['sub']),
              //    ,  sub  
              btnSub(){
                 this.sub()
              }
          }
      }
    </script>
    
    効果を見る:

    3.アクション:
    ここにきて、第四の大きな点の判例はすでに完成しました。すでに自己増加と自己減少が実現されました。今は判例を改善して、ボタンをクリックしてから一秒後に増減します。どうやって実現しますか?状態マシンのmutationの関数に1秒タイマーを追加してもいいですか?これは絶対だめです。mutationでは非同期操作を支持しないので、どうすればいいですか?
    _; アクションは任意の非同期動作を含むことができるので、非同期タスクを処理するために使用される。
     アクションは直接状態を変更するのではなく、mutationによって提出されます。stateのデータを直接修正することはできません。mutationだけが修正できます。つまり、非同期操作によってデータを変更する場合は、アクションによってMutationを使用することはできないが、ActionではMutationをトリガするように間接的にデータを変更する必要がある。
    まず状態マシンでアクションを定義します。
    
    export default new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        //   1  
        add(state){
          state.count++
        },
        //   1   
        sub(state){
          state.count--
        }
      },
      //   action,   addAsync    1    mutation  add  
       actions: {
        addAsync(context) {
          setTimeout(()=>{
          //     context.commit()  mutation  
             context.commit('add')
        },1000)
      }  
     }
    })
    
    アクション関数は、storeのインスタンスと同じ方法と属性を持つcontextオブジェクトを受け入れるので、context.co mmitを呼び出してmutationを提出することができます。
    3.1アクションをトリガする第1の方法:
    コンポーネントのAdd.vueコードを変更して、アクションを導入して、非同期の自己増加操作を実現します。
    
    <template>
        <div>
            <p>count  :{{this.$store.state.count}}</p>
               <button @click="btnAdd">+1</button>
        </div>
     
    </template>
    <script>
      export default{
          data() {
              return {
                  
              }
          },
          methods: {
              btnAdd() {
                  //      Action   ,  addAsync  
                  //    dispatch      action  
                  this.$store.dispatch('addAsync')
              }
          }
      }
    </script>
    
    効果を見て、1秒後に増加します。

    3.2アクション非同期タスクをトリガし、パラメータを伝える:
    もちろん、コンポーネントの中でactionの関数を呼び出した時もパラメータを伝えることができます。
    例えば、1秒をクリックしてから実行する自己増加関数がありますが、呼び出し時に入ってきたパラメータをどれだけ増やしたらいいですか?
    定義:
    
    export default new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
       //     ,      state,         
        //    n    
        addN(state,n){
          state.count+= n
        }
      },
       actions: {
        //     n,  n    mutation  addN  
        addNAsync(context,n) {
          setTimeout(()=>{
             context.commit('addN',n)
        },1000)
      }  
     }
    })
    
    対応するコンポーネントの呼び出し時にパラメータを入力します。
    
      methods: {
              btnAdd2() {
                  //   dispatch  
                  //   action    ,  6  ,    6
                  this.$store.dispatch('addNAsync',6)
              }
          }
    
    3.3アクションをトリガする第2の方法:
    (1)vuexから必要に応じてmapActions関数を導入する
    
    import { mapActions } from 'vuex'
    
    (2)先ほど導入したmapActions関数により、必要なactions関数を現在のコンポーネントのmethodsにマッピングする方法:
    
    methods: {
       ...mapActions(['add','addN'])
    }
    
    実戦で、Reduce.vueコンポーネントのクリックを一秒後にマイナス1の機能要求を実現します。
    actionsのsubAsyncを一秒後の自己減算関数として定義します。
    
    export default new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        //   1  
        add(state){
          state.count++
        },
        //   1   
        sub(state){
          state.count--
        }
      },
       actions: {
        addAsync(context) {
          setTimeout(()=>{
             context.commit('add')
        },1000)
      },
       subAsync(context) {
          setTimeout(()=>{
             context.commit('sub')
        },1000)
      }    
     }
    })
    
    
    Reduce.vueコードを変更して、機能を実現します。
    
    <template>
        <div>
             <p>count  :{{count}}</p>
               <button @click="btnSub">-1</button>
        </div>
    </template>
    <script>
    //  
    import {mapState,mapActions} from 'vuex'
      export default{
          data() {
              return {
                  
              }
          },
          computed: {
             ...mapState(['count'])
          },
          methods: {
              //   Action    
              ...mapActions(['subAsync']),
              //    ,  subAsync  
              btnSub(){
                 this.subAsync()
              }
          }
      }
    </script>
    
    効果を見る:

    4.Getter:
    Store内のデータを加工処理して新たなデータを形成するために  Getterを使用します。なお、stateのデータは修正されないので注意が必要です。
    ①GetterはStoreに既存のデータを加工して、Vueの計算属性に似た新しいデータを形成することができます。
    ②Storeでデータが変化し、Getterのデータも変化します。
    例えば、現在のcount+1を返すgetter関数があります。
    
    export default new Vuex.Store({
      state: {
        count: 0
      },
     getters: {
        showNum(state){
          return`  count  1 :${state.count+1}`
        }
      }
    })
    
    4.1 gettersをトリガする最初の方法:
    
    this.$store.getters.  
    
    App.vueコンポーネントに表示されます。
    
    <template>
      <div id="app">
           <my-add></my-add>
           <p>--------------------</p>
           <my-reduce></my-reduce>
           <p>--------------------</p>
           <h3>{{this.$store.getters.showNum}}</h3>
      </div>
    </template>
    
    効果:

    4.2 gettersをトリガする第二の方式:
    (1)vuexから必要に応じてmapGetters関数を導入する
    
    import { mapGetters } from 'vuex'
    
    (2)先ほど導入したmapGetters関数により、現在のコンポーネントに必要なグローバルデータを、現在のコンポーネントのcomputedにマッピングして属性を計算する:
    
    computed: {
       ...mapGetters(['showNum'])
    }
    
    それともApp.vueで使うべきですか?
    
    <template>
      <div id="app">
           <my-add></my-add>
           <p>--------------------</p>
           <my-reduce></my-reduce>
           <p>--------------------</p>
           <h3>{{showNum}}</h3>
      </div>
    </template>
    
    <script>
    //     
    import Add from './components/Add.vue'
    import Reduce from './components/Reduce.vue'
    //    mapGetters  
    import {mapGetters} from 'vuex'
    export default {
      name: 'App',
      data() {
        return {
          
        }
      },
      components: {
        'my-add': Add,
        'my-reduce': Reduce
      },
      //    getter
      computed: {
        ...mapGetters(['showNum'])
      }
    
    }
    </script>
    
    ほら、同じ効果です。

    六.まとめ:
    ここで、Vuexステータスマシンの迅速な理解と実例的なアプリケーションについての記事を紹介します。Vuexに関するアプリケーションの内容は以前の文章を検索したり、以下の関連記事を見たりしてください。これからもよろしくお願いします。