
カットの下には、「Vuex」の章の形式の抜粋があり、以下を説明しています。 ゲッターの使用。 突然変異の実施; アクションの追加。 Vuexヘルパーメソッドを使用します。 モジュールとプロジェクト設定。
10.1。 Vuexが必要な理由
Vuexライブラリは状態を管理します。 中央に保存されるため、コンポーネントに簡単にアクセスできます。 ステータスは、アプリケーションをサポートする情報またはデータです。 この情報を操作するための信頼できる理解可能なメカニズムが必要なので、これは重要です。
単一ページのアプリケーションを作成するために他のフレームワークを使用した経験がある場合、これらの概念のいくつかはおなじみのように思えるかもしれません。 たとえば、ReactはReduxと呼ばれる同様の状態管理システムを使用します。 VuexとReduxはFluxプロジェクトの影響を受けています。 これはFacebookによって提案されたアーキテクチャであり、クライアントWebアプリケーションの構築を簡素化するように設計されています。 これは、アクションからディスパッチャ、リポジトリ、そして最後にビューへの一方向のデータの移動に貢献します。 このアプローチにより、状態をアプリケーションの他の部分から分離し、同期更新を促進できます。 Fluxの詳細については、facebook.github.io / flux / docs / overview.htmlの公式ドキュメントをご覧ください。
Vuexは同じ原理で動作し、状態を予測可能かつ同期的に変更するのに役立ちます。 開発者は、同期および非同期関数で状態を更新することの結果について心配する必要はありません。 JSON形式でデータを返すサーバーAPIと対話していることを想像してください。 このデータがサードパーティのライブラリによって同時に変更されるとどうなりますか? 予測不可能な結果を望んでいません。 Vuexは、非同期の変更を排除することにより、このような状況を回避するのに役立ちます。
おそらく、Vuexライブラリが必要なのか疑問に思われるでしょう。 最終的に、Vue.jsを使用すると、コンポーネントに情報を渡すことができます。 前の章からわかるように、入力パラメーターとユーザーイベントはこのためのものです。 データ転送およびコンポーネント間通信用に独自のイベントバスを作成することもできます。 そのようなメカニズムの例を図に示します。 10.1。
これは、少数のコンポーネントを持つ小さなアプリケーションに適しています。 この場合、少数の受信者のみに情報を転送する必要があります。 しかし、アプリケーションがより大きく、より複雑で、階層化されている場合はどうでしょうか? 大規模なプロジェクトでは、すべてのコールバック関数、入力パラメーター、イベントを追跡するのはそれほど簡単ではないことは明らかです。
そのような状況のために、Vuexライブラリが作成されました。 これにより、中央リポジトリーの形で状態との作業を整理できます。 Vuexの使用を検討する価値のあるシナリオを想像してください。 たとえば、私たちはあなたが作成、編集、削除できる記事やコメントを含むブログに取り組んでいます。 同時に、ユーザーをブロックおよび追加できる管理パネルがあります。
Vuexを使用してこれがどのように実装されるかを見てみましょう。 図 図10.2は、EditBioコンポーネントが管理パネルの子であることを示しています。 ユーザー情報を更新するには、ユーザー情報にアクセスする必要があります。 Vuexを使用して、中央リポジトリにアクセスし、データを変更して、EditBioコンポーネントから直接変更を保存できます。 これは、Vue.jsのルートインスタンスからAdminコンポーネントに情報を渡し、入力パラメーターを使用してEditBioに情報を渡すよりもはるかに優れています。 別の場所にあるデータを追跡することは困難です。


それでも、Vuexの使用には、追加の定型コードとアプリケーション構造の複雑さという形での代償が伴います。 既に述べたように、いくつかのコンポーネントで構成される単純なプロジェクトでは、このライブラリを使用しない方が良いでしょう。 その本当の可能性は、より複雑な状態の大規模なアプリケーションで明らかになります。
10.2。 Vuexの状態と突然変異
Vuexは、アプリケーション全体の状態を単一のオブジェクトに保存します。これは、単一の真実のソースとも呼ばれます。 名前が示すように、すべてのデータは1か所で収集され、コードの他の部分では複製されません。
ヒントVuexで状態を操作する簡単な例を考えてみましょう。 すべてのコードは1つのファイルに配置されます。 後で、Vue-CLIを使用してVuexをプロジェクトに追加する方法を学習します。 テキストエディターを開き、vuex-state.htmlファイルを作成します。 中央リポジトリにあるメッセージとカウンターを表示します。 結果を図に示します。 10.3。
すべてのデータをVuexに保存する必要はないことに注意してください。 個々のコンポーネントには、独自のローカル状態があります。 特定の状況では、これが望ましいです。 たとえば、コンポーネントには、その内部でのみ使用される変数があります。 彼女は地元にいなければなりません。

ボタン要素は、増分アクションをトリガーします。 リスト10.1のコードをvuex-state.htmlファイルにコピーします。

HTMLマークアップが完了したら、Vuexリポジトリの作成を始めましょう。 これには、msgおよびcountプロパティを含むすべてのアプリケーションデータが含まれます。
状態を更新するには、突然変異を使用します。 これは、他のプログラミング言語のセッターのようなものです。 セッターは値を設定し、ミューテーションはプログラムの状態を更新します。 Vuexでは、突然変異は同期的でなければなりません。 この例では、カウンターはボタンをクリックするだけでインクリメントされるため、非同期コードを心配する必要はありません(非同期の問題を解決するアクションを見ていきます)。
状態をインクリメントするMutationsオブジェクト内にインクリメント関数を作成します。 リスト10.2のコードを取得し、vuex-state.htmlファイルの下部に貼り付けます。

そのため、HTMLマークアップとVuexリポジトリを準備しました。 これで、それらを接続するロジックを追加できます。 テンプレートにVuex状態の一部であるmsg値とcounter値を表示する必要があります。 さらに、カウンターを更新する必要があります。
Vue.jsのインスタンスを作成し、Vuex Appのテキストを含むローカルヘッダープロパティを返す新しいデータ関数を使用します。 計算セクションで、計算プロパティwelcomeおよびcounterを追加します。 最初はstore.state.msgを返し、2番目はstore.state.countを返します。
最後に、incrementというメソッドを追加する必要があります。 Vuexリポジトリで突然変異が宣言されましたが、それを直接使用して状態を更新することはできません。 このために特別なコミット機能が提供されています。 Vuexにリポジトリを更新するように指示し、変更を保存します。 式store.commit( 'increment')は突然変異を実行します。 リスト10.2で作成したコードの直後に、次のスニペット(リスト10.3)を挿入します。

これは、Vuexに基づいた本格的な動作中のアプリケーションです! ボタンを押してみてください-カウンターを押すたびに1ずつ増加します。
ボタンを押すとカウンタが10増えるようにコードを更新します。インクリメントミューテーションをよく見ると、引数が1つだけであることがわかります。 別のものを渡しましょう-それをペイロードと呼びましょう。 Vue.jsのルートインスタンスで作成されるincrementメソッドによって渡されます。
vuex-state.htmlの内容を新しいvuex-state-pass.htmlファイルにコピーします。 このアプリケーションを例として使用して、引数がどのように渡されるかを示します。
リスト10.4を見るとわかるように、mutationsオブジェクトとincrementメソッドのみを更新する必要があります。 ミューテーションインクリメントに、ペイロードと呼ばれる別の引数を追加します。 これは、state.countが増加する値です。 incrementメソッド内でstore.commitの呼び出しを見つけ、2番目の引数として10を指定します。 以下に示すようにvuex-state.htmlファイルを更新します。

vuex-state-pass.htmlファイルを保存して、ブラウザーで開きます。 これで、ボタンが押されると、カウンターは1ではなく10増加します。何か問題が発生した場合は、ブラウザーコンソールを確認し、タイプミスがないことを確認します。
10.3。 ゲッターとアクション
前の例では、計算されたプロパティから直接ストアにアクセスしました。 しかし、同じアクセスを必要とする複数のコンポーネントがある場合はどうでしょうか? ウェルカムメッセージを大文字で表示するとします。 この場合、ゲッターが役立ちます。
ゲッターはVuexの一部です。 これらを使用すると、すべてのコンポーネントの状態への統合アクセスを実装できます。 セクション10.2の例を見てみましょう。計算されたプロパティを介してリポジトリに直接アクセスする代わりに、ゲッターを使用します。 さらに、msgプロパティのgetterですべての文字を大文字に変換します。
vuex-state-pass.htmlファイルの内容をvuex-state-getter-action.htmlにコピーします。 タスクを簡素化するには、HTMLコードを変更しないでください。 最終的に、図に似たものが得られるはずです。 10.4。

新しいvuex-state-getter-action.htmlファイル内のタグのすぐ下にあるVuex.Storeコンストラクトを見つけます

msgゲッターはstate.msg.toUppercase()を返します。 これにより、メッセージは常に大文字で表示されます。 get getterでは、state.countを返します。 突然変異の下にゲッターを追加すると、vuex-state-getter-action.htmlファイルは次のようになります。

アクションはVuexのもう1つの不可欠な部分です。 先に述べたように、突然変異は同期的でなければなりません。 しかし、非同期コードを使用するとどうなりますか? 非同期呼び出しで状態を変更できるようにする方法は? Vuexアクションはこれに役立ちます。
アプリケーションがサーバーにアクセスし、応答を待っていると想像してください。 これは非同期アクションの例です。 残念ながら、突然変異は非同期であるため、ここでは使用できません。 代わりに、Vuexアクションに基づいて非同期操作を追加します。
遅延を作成するには、setTimeout関数を使用します。 vuex-state-getter-action.htmlファイルを開き、ゲッターの直後にアクションオブジェクトを追加します。 このオブジェクト内に、コンテキスト引数とペイロード引数を取るインクリメントアクションを配置します。 コンテキストを使用して、変更を保存します。 context.commit操作をsetTimeout内に配置します。 このようにして、サーバーの遅延をシミュレートします。 ペイロード引数をcontext.commitに渡すこともできますが、この引数は変更になります。 リスト10.6に基づいてコードを更新します。
Vuex.Storeを更新したら、Vue.jsのルートインスタンスに進むことができます。 計算されたプロパティは、以前のようにストアに直接アクセスしませんが、ゲッターを使用します。 また、incrementメソッドも変更しています。 前に作成した新しいVuexプロパティにアクセスするには、store.dispatch( 'increment'、10)の呼び出しを使用します。

ディスパッチ呼び出しの最初の引数はアクションの名前であり、2番目の引数には常にこのアクションに渡される追加データが含まれます。
ヒント
追加のデータは、通常の変数またはオブジェクトですらあります。
リスト10.7に示すように、vuex-state-getter-action.htmlファイルのVue.jsインスタンスを更新します。

アプリケーションをダウンロードし、ボタンを数回押します。 遅延に気付くはずですが、カウンターはクリックごとに10ずつ増加します。
10.4。 Vue-CLIを使用してペットストアプロジェクトでVuexを使用する
私たちが取り組んでいたペットショッププロジェクトに戻ります。 忘れていないのであれば、アニメーションとトランジションを追加することに決めました。 ここで、以前に出会ったVuexライブラリを統合します。
商品のデータを倉庫に転送します。 前の章で思い出したように、データはメインコンポーネント内に作成されたフックで初期化されました。 このフックは、Vuexリポジトリを初期化する新しいイベントを生成するはずです。 また、ゲッターを使用して製品を取得する計算プロパティ製品も追加します(後で作成します)。 最終結果は図のようになります。 10.5。

10.4.1。 Vue-CLIを使用してVuexをインストールする
まず、Vuexをインストールしてください! これは簡単なプロセスです。 第8章で取り組んだペットストアの最新バージョンを準備します。この章のすべてのコードは、github.com / ErikCH / VuejsInActionCodeのGitHubでもダウンロードできます。
ターミナルウィンドウを開き、プロジェクトのルートディレクトリに移動します。 Vuexの最新バージョンをインストールするには、次のコマンドを実行します。
$ npm install vuex
ペットストアのpackage.jsonファイルにそのレコードを保存します。
ここで、srcフォルダーにあるmain.jsファイルにストレージを追加する必要があります。 リポジトリ自体はまだ存在しませんが、とにかくインポートします。 通常はsrc / store / store.jsファイルにありますが、別のパスを選択できます-すべての開発者が独自の設定を持っています。 一般的に受け入れられているオプションについて説明します。 この章の後半では、モジュールを使用した代替ディレクトリ構造について説明します。
リスト10.8に示すように、ルーターの下のVue.jsのルートインスタンスにストレージを追加する必要があります。 ところで、ES6標準を使用しているため、store:storeはstoreに短縮できます。

ストレージをルートインスタンスに接続すると、アプリケーションのどの部分からでもアクセスできます。 src / store / store.jsファイルを作成します。 その中に、ペットショップが提供する製品に関する情報を含むVuexリポジトリを配置します。 上部に、VueおよびVuex用の2つのインポートステートメントを追加します。 次に、Vue.use(Vuex)を指定してすべてをまとめます。
main.jsファイルのリポジトリを./store/storeからインポートしました。 次に、store.js内でストアオブジェクトをエクスポートする必要があります。 リスト10.9でわかるように、Vuex.Storeに等しいconstストア値をエクスポートします。
最初に、状態と突然変異を含むオブジェクトを追加します。 状態には、製品と呼ばれる空のオブジェクトが含まれます。 すぐにinitStoreメソッドで埋めます。 突然変異はSET_STOREと呼ばれ、転送された商品をstate.productsプロパティに割り当てます。 次のリストのコードを、作成したsrc / store / store.jsファイルに貼り付けます。

リポジトリにアクションとゲッターを作成する必要があります。 ゲッターは製品オブジェクトを返します。 アクションはもう少し複雑です。 Axiosを使用してstatic / products.jsonファイルを読み取る作成済みのフックを、Vuex内のアクションオブジェクトに転送する必要があります。
先に、突然変異は同期的でなければならず、Vuex内のアクションのみが非同期コードを受け入れることができると述べました。 この制限を回避するには、VuexアクションにAxiosコードを配置します。
store.jsファイルにアクションオブジェクトを作成し、それにinitStoreメソッドを追加します。 作成したフックの内容をcomponents / Main.vueファイルからこのメソッドにコピーします。 response.data.productsをproductsオブジェクトに割り当てる代わりに、commit関数を使用して変更を呼び出します。 response.data.productsを引数としてSET_STOREに渡します。 結果のコードは次のようになります(リスト10.10)。

ほぼ完了しました。Main.vueファイルを更新し、商品をローカル製品オブジェクトからVuexリポジトリに転送するだけです。 src / components / Main.vueファイルを開き、データ関数を見つけます。 ライン製品を削除します:{}。 ストアが返す計算されたプロパティから商品にアクセスします。
Main.vue内で計算されたプロパティcartItemCountとsortedProductsを見つけます。これらはメソッドセクションの直後に移動します。 productsプロパティを追加し、同じ名前のゲッターを返すようにします。
main.jsファイルでVue.jsのルートインスタンスにリポジトリを接続したため、インポートする必要はありません。 さらに、Vue-CLIを使用する場合、ストレージは常にこの形式で利用できます。 $記号を忘れないでください。忘れるとエラーになります。 リスト10.11に示すように、計算プロパティを製品に追加します。

製品オブジェクトが初期化されている作成済みのフックを見つけて、その内容を削除します。 代わりに、前に作成したinitStoreアクション呼び出しをVuexリポジトリに挿入します。 アクションを呼び出すには、前の例のようにディスパッチ機能を使用します。 リスト10.12は、Main.vueファイルを更新した後、作成されたフックがどのように見えるかを示しています。

それで十分でしょう。 ターミナルでnpm run devコマンドを実行すると、ペットストアアプリケーションを含むウィンドウが画面に表示されます。 製品をバスケットに入れて、すべてが正常に機能していることを確認してください。 問題が発生した場合は、コンソールでエラーを探してください。 Vuex.storeの代わりにsrc / store / store.jsファイルで、誤ってVuex.Storeと入力できます。 これを覚えて!
10.5。 ヘルパーメソッドVuex
Vuexは、コードをより簡潔にし、同じゲッター、セッター、ミューテーション、アクションを追加することをなくす便利なヘルパーメソッドを提供します。 Vuexヘルパーメソッドの完全なリストについては、vuex.vuejs.org / guide / core-concepts.htmlの公式ガイドを参照してください。 それらがどのように機能するかを見てみましょう。
知っておくべき主なヘルパーメソッドはmapGettersと呼ばれます。 利用可能なすべてのゲッターを計算セクションに追加するために使用され、それぞれをリストする必要はありません。 ただし、使用する前に、コンポーネント内にインポートする必要があります。 もう一度、ペットストアに戻り、mapGettersメソッドを追加します。
src / components / Main.vueファイルを開き、scriptタグを見つけます。 このタグ内のどこかに、Headerコンポーネントをインポートする必要があります。 リスト10.13に示すように、このインポートの直後にmapGettersを接続します。

次に、計算されたプロパティを更新する必要があります。 計算セクションで製品関数を見つけ、その場所にmapGettersオブジェクトを挿入します。
mapGettersは一意のオブジェクトです。適切な操作を行うには、ES6のspread演算子を使用する必要があります。引数が予想される状況(0以上)で式を展開します。 developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_syntaxの MDNドキュメントでこの構文の詳細を読むことができます。
mapGettersは、すべてのゲッターが計算されたプロパティとして追加されるようにします。 これは、ゲッターごとに個別の計算されたプロパティを記述するよりもはるかにシンプルでエレガントな方法です。 すべてのゲッターはmapGetters配列にリストされています。 このヘルパーメソッドをMain.vueファイルに追加します(リスト10.14)。

npm run devコマンドを実行すると、ペットストアは以前と同じように動作するはずです。 mapGettersヘルパーメソッドはこれまでのところあまり役に立ちませんが、ゲッターを追加するほど、時間を節約できます。
知っておくべき3つのヘルパーメソッドがあります:mapState、mapMutations、およびmapActions。 これらはすべて同様に機能し、手動で記述する必要のある定型コードの量を減らします。
リポジトリに複数のデータが含まれており、ゲッターを使用せずにコンポーネントから状態へのアクセスが直接実行されると想像してください。 この場合、計算セクション内でmapStateメソッドを使用できます(リスト10.15)。

ここで、コンポーネントで複数の突然変異を使用する必要があると想像してください。 このプロセスを簡素化するには、mapStateおよびmapGettersで行われるように、mapMutationsヘルパーメソッド(リスト10.16)を使用します。 次のmut1はthis.mut1()をthis。$ Store.commit( 'mut1')にバインドします。

最後に、mapActionsヘルパーメソッドを検討します。 Vuexアクションをアプリケーションに追加できるため、それぞれの場合にディスパッチ呼び出しでメソッドを作成する必要がなくなります。 前の例に戻って、アプリケーションに非同期操作が含まれていることを想像してください。 突然変異の使用は除外されているため、行動に頼らなければなりません。 Vuexで作成した後、コンポーネントのメソッドオブジェクトでそれらにアクセスする必要があります。 この問題は、mapActionsを使用して解決できます。 リスト10.17に示すように、act1はthis.act1()をthis。$ store.dispatch( 'act1')にバインドします。

最後に、mapActionsヘルパーメソッドを検討します。 Vuexアクションをアプリケーションに追加できるため、それぞれの場合にディスパッチ呼び出しでメソッドを作成する必要がなくなります。 前の例に戻って、アプリケーションに非同期操作が含まれていることを想像してください。 突然変異の使用は除外されているため、行動に頼らなければなりません。 Vuexで作成した後、コンポーネントのメソッドオブジェクトでそれらにアクセスする必要があります。 この問題は、mapActionsを使用して解決できます。 リスト10.17に示すように、act1はthis.act1()をthis。$ store.dispatch( 'act1')にバインドします。

アプリケーションが成長するにつれて、これらのヘルパーメソッドはますます有用になり、記述する必要のあるコードの量が減ります。 ヘルパーメソッドを使用するとコンポーネント内でプロパティにアクセスできるため、リポジトリ内のプロパティ名を検討する必要があることに注意してください。
10.6。 モジュールの簡単な紹介
この章の最初に、src / storeディレクトリにstore.jsファイルを作成しました。 小さなプロジェクトの場合、このアプローチは非常に適切です。 しかし、もっと大きなアプリケーションを扱っている場合はどうでしょうか? store.jsファイルは急速に成長し、その中で発生するすべてを追跡することは困難になります。
この問題を解決するために、Vuexはモジュールの概念を提供しています。 モジュールを使用すると、ストレージをいくつかの小さな部分に分割できます。 各モジュールには独自の状態、突然変異、アクション、およびゲッターがあり、それらを互いに入れ子にすることもできます。
モジュールを使用してペットストアを書き換えます。 store.jsファイルはそのまま残りますが、その隣にmodulesフォルダーを作成し、そこにproducts.jsファイルを配置する必要があります。 ディレクトリ構造は、図1のようになります。 10.6。

src / store / store.jsファイルを開き、そこからコードのコピーを開始します。 完了したら、products.jsファイルは次のようになります(リスト10.18)。
ここで、product.jsファイルに追加したすべてのコードをエクスポートする必要があります。 これにより、store.jsにインポートされます。 ファイルの下部に、式のエクスポートのデフォルトを追加します。 これは、このコードを他のファイルからインポートできるようにするES6形式のエクスポート命令です(リスト10.19)。
store.jsファイルを更新する必要があります。 モジュールオブジェクトをそれに追加します。その中に、すべての新しいモジュールをリストできます。 前に作成したモジュール/製品ファイルを忘れずにインポートしてください。

この例にはモジュールが1つしか含まれていないため、すぐにモジュールオブジェクトに追加します。 リスト10.20に示すように、Vuex.Storeから不要なものをすべて削除する必要もあります。

モジュールをインポートすることで、リファクタリングプロセスが完了しました。 ページを更新すると、アプリケーションは以前とまったく同じように動作するはずです。
Vuexの名前空間»本の詳細については、出版社のウェブサイトをご覧ください
一部の大規模プロジェクトでは、モジュール化により特定の問題が発生する場合があります。 新しいモジュールが追加されると、アクション、ゲッター、ミューテーション、および状態プロパティの名前との競合が発生する可能性があります。 たとえば、異なるファイル内の2つのゲッターに同じ名前を誤って割り当てる場合があります。 また、すべてがVuexの共通グローバルネームスペースにあるため、コンソールで重複キーエラーが発生します。
この問題を回避するには、各モジュールを個別のネームスペースに配置します。 これを行うには、Vuex.storeの上部でnamespaced:trueを指定するだけです。 この機能の詳細については、vuex.vuejs.org / en / guide / modules.htmlの公式Vuexドキュメントを参照してください。
» コンテンツ
» 抜粋
ホーカーのクーポンが25%オフ-Vue.js
本の紙版が支払われると、電子版の本が電子メールで送信されます。