Vuex 学習メモ
これは何か
Vuex の公式ドキュメントを読んだときのメモです。
気になったところ、後でもう一度確認が必要そうなもの、など。
Vuex のバージョンは v3.0.1。
Vuex ガイド
Vuex とは何か?
他のパターンと異なるのは、Vuex は効率的な更新のために、Vue.js の粒度の細かいリアクティビティシステムを利用するよう特別に調整して実装されたライブラリだということです。
Vuex 入門
- Vuex ストアはリアクティブです。Vue コンポーネントがストアから状態を取り出すとき、もしストアの状態が変化したら、ストアはリアクティブかつ効率的に更新を行います。
- ストアの状態を直接変更することはできません。明示的にミューテーションをコミットすることによってのみ、ストアの状態を変更します。これによって、全ての状態の変更について追跡可能な記録を残すことが保証され、ツールでのアプリケーションの動作の理解を助けます。
store.state.count を直接変更する代わりにミューテーションをコミットする理由は、状態の変更を明確に追跡したいからです。このシンプルな規約は、あなたのコードの意図をさらに明確にし、コードを読んだ時にアプリケーションの状態の変更について、論理的に考えることができるようにします。加えて、私たちに全ての変更のログを取ったり、状態のスナップショットを取ったり、タイムトラベルデバッグを行うようなツールを実装する余地を与えてくれます。
コアコンセプト
ステート
Vuex は 単一ステートツリー (single state tree) を使います。
mapState
ヘルパー
ゲッター
算出プロパティと同様に、ゲッターの結果はその依存関係に基づいて計算され、依存関係の一部が変更されたときにのみ再評価されます。
- プロパティスタイルアクセス
ゲッターは
store.getters
オブジェクトから取り出され、プロパティとしてアクセスすることができます:ゲッターは第2引数として他のゲッターを受け取ります:
プロパティとしてアクセスされるゲッターは Vue のリアクティブシステムの一部としてキャッシュされるという点に留意してください。
- メソッドスタイルアクセス
関数を返り値にすることで、ゲッターに引数を渡すこともできます。
メソッドによってアクセスされるゲッターは呼び出す度に実行され、その結果はキャッシュされない点に留意してください。
mapGetters
ヘルパー
ミューテーション
store.commit('increment')
store.commit('increment', 10)
store.commit({ type: 'increment', amount: 10 })
- Vue のリアクティブなルールに則ったミューテーション
- あらかじめ全ての必要なフィールドによって、ストアの初期状態を初期化することが望ましいです
- 新しいプロパティをオブジェクトに追加するとき、以下のいずれかが必要です:
- Vue.set(obj, 'newProp', 123) を使用する。あるいは
- 全く新しいオブジェクトで既存のオブジェクトを置き換える。
- ミューテーション・タイプに定数を使用する
- ミューテーションは同期的でなければならない
アクション
アクションは、状態を変更するのではなく、ミューテーションをコミットします。 アクションは任意の非同期処理を含むことができます。
したがって
context.commit
を呼び出すことでミューテーションをコミットできます。あるいはcontext.state
やcontext.getters
で、状態やゲッターにアクセスできます。なぜコンテキストオブジェクトがストアインスタンスそのものではないのかは、後ほどモジュールで説明します。
mapActions
ヘルパー- vuex-101-promise - StackBlitz
- Promise, async / await を利用したデモ
実践的な例として、ショッピングカートをチェックアウトするアクション
actions: { checkout ({ commit, state }, products) { // 現在のカート内の商品を保存する const savedCartItems = [...state.cart.added] // チェックアウトのリクエストを送信し、楽観的にカート内をクリアする commit(types.CHECKOUT_REQUEST) // shop API は成功時のコールバックと失敗時のコールバックを受け取る shop.buyProducts( products, // 成功時の処理 () => commit(types.CHECKOUT_SUCCESS), // 失敗時の処理 () => commit(types.CHECKOUT_FAILURE, savedCartItems) ) } }
モジュール
- vuex-101-module - StackBlitz
- デモ
context.state
,context.rootState
- 名前空間
デフォルトでは、モジュール内部のアクション、ミューテーション、そしてゲッターはグローバル名前空間の元で登録されます - これにより、複数のモジュールが同じミューテーション/アクションタイプに反応することができます。
namespaced: true
- 名前空間付きモジュールでのグローバルアセットへのアクセス
アクションをディスパッチするか、グローバル名前空間にミューテーションをコミットするには、dispatch と commit の3番目の引数として {root: true} を渡します。
- 名前空間によるバインディングヘルパー
...mapState({ a: state => state.some.nested.module.a,
...mapState('some/nested/module', {
,const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
- 動的にモジュールを登録する
store.registerModule
- (あとで読む)
- モジュールの再利用
- (あとで読む)
アプリケーションの構造
プラグイン
- vuex-101-plugins - StackBlitz
- デモ
Vuex ストア は、各ミューテーションへのフックを公開する plugins オプションを受け付けます。 Vuex プラグインは、単一の引数としてストアを受けつけるただの関数です:
- プラグイン内でのミューテーションのコミット
ミューテーションのコミットによるストアとデータソースの同期をプラグインで実現できます。
- (あとで読む)
- 状態のスナップショットを撮る
- (あとで読む)
- ビルトインロガープラグイン
createLogger
厳格モード
strict: true
本番環境で厳格モードを有効にしてデプロイしてはいけません! 厳格モードでは不適切なミューテーションを検出するためにステートツリーに対して深い監視を実行します。パフォーマンスコストを回避するために本番環境では無効にしてください。
フォームの扱い
- vuex-101-forms - StackBlitz
- デモ
厳格モードでは、この変更は明示的に Vuex のミューテーションハンドラ内部で処理されていないため、エラーを投げます。
テスト
- (あとで読む)
ホットリローディング
- (あとで読む)