Vuexを使用してVue.jsアプリケーションの状態を管理する方法
著者は、 Write for DOnations プログラムの一環として、 Open Sourcing MentalIllnessを選択して寄付を受け取りました。
序章
Vuex は、Vue.js用のファーストパーティの開発状態管理ライブラリです。 これはEvanYouによって作成され、現在Vue.jsコアチームによって維持されています。 他の多くの状態管理ライブラリと同様に、Vuexは、 Redux が過去数年にわたって普及してきた原則に従います。データは一方向に流れ、アクションとミューテーションによって、ストアと呼ばれる信頼できる唯一の情報源のデータが変更されます。
Vuex store は、さまざまなメソッドとデータのコレクションです。 操作などのこれらのメソッドの一部は、データがミューテーションに送信される前にデータをフェッチして処理できます。 mutation は、提供された値でストアプロパティを変更または更新するメソッドです。 Getters は、データを変更または結合して新しい状態プロパティを作成できるメソッドです。 これらのゲッターは読み取り専用であり、データを変更しません。 これらは、Vue.jsコンポーネントの計算されたプロパティに似ています。 Vuexの最後のコンポーネントは、 state 、または信頼できる唯一の情報源として機能するデータセットです。
このチュートリアルでは、空港情報を含むカードのリストをレンダリングするアプリケーションを作成します。 クリックすると、これらのカードはVuexワークフローを実行して、選択した空港をお気に入りのリストに追加します。 この例を実行することにより、状態を管理するためのアクションとミューテーションを作成し、計算されたデータを取得するためのゲッターを作成します。
前提条件
- Node.jsバージョン
14.16.0
以降がコンピューターにインストールされています。 これをmacOSまたはUbuntu20.04にインストールするには、Node.jsをインストールしてmacOSにローカル開発環境を作成する方法またはのPPAを使用したインストール]セクションの手順に従います。 Ubuntu20.04にNode.jsをインストールする方法 - Vue CLIがマシンにインストールされ、新しいプロジェクトが生成されました。 アプリを生成するときは、必ず
Default (Vue 3 Preview)
オプションを選択してください。 このプロジェクトの名前はfavorite-airports
になり、ルートディレクトリとして機能します。 - また、JavaScript、HTML、およびCSSの基本的な知識も必要です。これは、 HTMLを使用してWebサイトを構築する方法シリーズ、CSSを使用してWebサイトを構築する方法シリーズにあります。 、およびJavaScriptでコーディングする方法。
ステップ1—サンプルアプリケーションのセットアップ
Vuexで状態がどのように管理されているかを視覚化するために、ビューに表示するデータを使用してプロジェクトを設定します。 このプロジェクトとチュートリアル全体で使用します。
前提条件セクションの説明に従ってfavorite-airports
プロジェクトが作成されたら、このプロジェクトのすべてのローカルデータを保持するディレクトリを作成します。 ターミナルを開き、プロジェクトのルートディレクトリ(favorite-airports
)で次のコマンドを実行します。
mkdir src/data touch src/data/airports.js
これにより、data
ディレクトリと、その中に空のairports.js
ファイルが作成されます。
選択したテキストエディタで、新しく作成したairports.js
ファイルを開き、以下を追加します。
お気に入り-airports/src / data / airports.js
export default [ { name: 'Cincinnati/Northern Kentucky International Airport', abbreviation: 'CVG', city: 'Hebron', state: 'KY' }, { name: 'Seattle-Tacoma International Airport', abbreviation: 'SEA', city: 'Seattle', state: 'WA', }, { name: 'Minneapolis-Saint Paul International Airport', abbreviation: 'MSP', city: 'Bloomington', state: 'MN', }, { name: 'Louis Armstrong New Orleans International Airport', abbreviation: 'MSY', city: 'New Orleans', state: 'LA', }, { name: `Chicago O'hare International Airport`, abbreviation: 'ORD', city: 'Chicago', state: 'IL', }, { name: `Miami International Airport`, abbreviation: 'MIA', city: 'Miami', state: 'FL', } ]
これは、米国内のいくつかの空港で構成されるオブジェクトの配列です。 このアプリケーションでは、このデータを反復処理して、name
、abbreviation
、city
、およびstate
プロパティで構成されるカードを生成します。 ユーザーがカードをクリックすると、dispatch
メソッドが実行され、その空港がお気に入りの空港としてVuex州に追加されます。
data/airports.js
を保存して、ターミナルに戻ります。
その手順が完了したら、AirportCard.vue
という名前の単一ファイルコンポーネント(SFC)を作成します。 このファイルは、プロジェクトのcomponents
ディレクトリにあります。 このコンポーネントには、エアポートカードのすべてのスタイルとロジックが含まれます。 ターミナルで、touch
コマンドを使用して.vue
ファイルを作成します。
touch src/components/AirportCard.vue
テキストエディタでAirportCard.vue
を開き、以下を追加します。
お気に入り-airports/src / components / AirportCard.vue
<template> <div class="airport"> <p>{{ airport.abbreviation }}</p> <p>{{ airport.name }}</p> <p>{{ airport.city }}, {{ airport.state }}</p> </div> </template> <script> export default { props: { airport: { type: Object, required: true } } } </script> <style scoped> .airport { border: 3px solid; border-radius: .5rem; padding: 1rem; margin-bottom: 1rem; } .airport p:first-child { font-weight: bold; font-size: 2.5rem; margin: 1rem 0; } .airport p:last-child { font-style: italic; font-size: .8rem; } </style>
このコードスニペットにCSSが含まれていることに気付くかもしれません。 AirportCard.vue
コンポーネントでは、ラッパー<div>
にairport
のクラスが含まれています。 このCSSは、各空港に「カード」の外観を与えるために境界線を追加することにより、生成されたHTMLにスタイルを追加します。 :first-child
と:last-child
は、div
内のHTMLの最初と最後のp
タグに異なるスタイルを適用する疑似セレクターです。 airport
のクラスで。 それに加えて、このコンポーネントには prop が含まれていることに気付くかもしれません。これは、Vue.jsでは親コンポーネントから子コンポーネントにデータを渡す方法です。
ファイルを保存して終了します。
セットアップを完了する前に、既存のApp.vue
コンポーネントを次のコードに置き換えます。
お気に入り-airports/src / App.vue
<template> <div class="wrapper"> <div v-for="airport in airports" :key="airport.abbreviation"> <airport-card :airport="airport" /> </div> </div> </template> <script> import { ref } from 'vue' import allAirports from '@/data/airports.js' import AirportCard from '@/components/AirportCard.vue' export default { components: { AirportCard }, setup() { const airports = ref(allAirports) return { airports } } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } .wrapper { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-column-gap: 1rem; max-width: 960px; margin: 0 auto; } p, h3 { grid-column: span 3; } </style>
このコードには、v-forループが含まれています。このループは、airports.js
データを反復処理し、プロップ:airport
を介して渡された空港データを使用して一連のAirportCards.vue
コンポーネントをレンダリングします。 ]。 このコードを保存して、コマンドラインに戻ります。
プロジェクトをセットアップしたら、ターミナルでnpm run serve
コマンドを使用してローカル開発サーバーを実行します。
npm run serve
これにより、localhost
で、通常はポート8080
でサーバーが起動します。 選択したWebブラウザーを開き、localhost:8080
にアクセスして以下を確認します。
サンプルアプリケーションがセットアップされたので、次のステップでVuexライブラリをインストールし、store
を作成します。 このストアは、状態、ミューテーション、アクション、ゲッターなど、さまざまなVuexアイテムのコレクションです。 これを説明するために、ディスパッチメソッドを実行します。これにより、アプリのお気に入りセクションに空港が追加されます。
ステップ2—Vuexをインストールする
Webベースのアプリケーションで作業する場合、多くの場合、stateで作業します。 状態は、特定の時点でのデータのコレクションです。 この状態は、dispatch
およびcommit
メソッドを介したユーザー操作によって変更できます。 ユーザーがデータを変更すると、ディスパッチイベントが実行され、データが mutation に渡され、state
オブジェクトが更新されます。
状態の更新にアプローチする方法はいくつかあります。 一部の開発者は、actions
をスキップして、mutatations
に直接進みます。 ただし、このチュートリアルでは、常にaction
を実行し、mutation
を呼び出します。 このようにして、アクション内に複数のミューテーションを含めることができます。 Vuexの基本的なルールは、ミューテーションには1つのジョブと1つのジョブのみがあるということです。ストアを更新します。 アクションは、データの結合、データのフェッチ、JavaScriptロジックの実行など、さまざまなことを実行できます。
アクションに加えて、gettersもあります。 ゲッターは、複数の状態値を1つの値に結合する方法です。 Vue.jsの計算されたプロパティに精通している場合、ゲッターは状態固有の計算されたプロパティと考えることができます。
Vuexの用語をカバーしたら、Vuexのインストールと統合を開始します。 ターミナルを開き、次のコマンドを実行します。
npm install vuex@next --save
このコマンドは、Vue.js 3.xと最も互換性のあるバージョンのVuexをインストールし、package.json
ファイルに保存します。 次に、ストアのディレクトリとインデックスファイルを作成します。 mkdir
コマンドを使用してディレクトリを作成し、touch
を使用して新しいファイルを作成します。
mkdir src/store touch src/store/index.js
テキストエディタを開き、store/index.js
ファイルでVuexストアを初期化します。 これを行うには、VuexのcreateStore
関数を利用する必要があります。
空港-favorites/src / store / index.js
import { createStore } from 'vuex' export default createStore({ })
また、後でmain.js
ファイルにインポートするため、これをexport
します。
この時点で、Vuexストアがセットアップされていますが、アプリケーションはまだVuexストアまたはその使用方法を認識していません。 ストアを完全に初期化するには、import
をmain.js
ファイルに入れます。 テキストエディタで、src/main.js
ファイルを開きます。
createApp(App)
の直後に、use
メソッドをチェーンし、次の強調表示されたコードに示すように、インポートするストアに渡します。
お気に入り-airports/src / main.js
import { createApp } from 'vue' import App from './App.vue' import store from './store' createApp(App).use(store).mount('#app')
use
メソッドを連鎖させたら、このファイルを保存します。 use
メソッドは、アプリケーションのビルド時にどのコードをバンドルするかをVueアプリケーションに指示します。 この場合、Vuexストアを「使用」またはバンドルするようにVueに指示しています。
次のセクションに進む前に、状態値をストアに追加し、App.vue
ファイルで参照してください。 store/index.js
ファイルを開き、次のオブジェクトと値を追加します。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' export default createStore({ state: { firstName: 'John', lastName: 'Doe' }, mutations: { }, actions: { }, getters: { } })
これらのプロパティは、ストアが保持するデータのタイプを反映します。状態(グローバルデータ)のstate
、mutations
(データを変更することをコミット)、actions
(変更を呼び出すディスパッチ)、およびgetters
(store
計算されたプロパティ)。
store/index.js
を保存し、テキストエディタでApp.vue
ファイルを開いて、次を追加します。
お気に入り-airports/src / App.vue
<template> <div class="wrapper"> <p>{{ $store.state.firstName }} {{ $store.state.lastName }}</p> <div v-for="airport in airports" :key="airport.abbreviation"> <airport-card :airport="airport" /> </div> </div> </template> ...
この場合の$store
は、main.js
ファイルで初期化したグローバルストアです。 this.$store
をコンソールにログインすると、ストアobject
が表示されます。 そこから、コードはドット表記を介して表示するプロパティにアクセスします。
App.vue
を保存して、Webブラウザを開きます。 空港カードの上に、Vuexストアに保存した名前と名前が表示されます。 これらは、それぞれfirstName
とlastName
のデフォルト値です。
このステップでは、Vuexをインストールし、Vuexストアを作成しました。 いくつかのデフォルトのストアデータを追加し、ドットの概念を使用して$store
オブジェクトとともにビューに表示しました。 次のステップでは、actions
およびmutations
を介してVuexストアを更新し、getters
と組み合わせたデータを取得します。
ステップ3—アクション、ミューテーション、およびゲッターを作成する
ステップ2では、Vuexを手動でインストールし、プロジェクトに統合しました。 このステップでは、ブラウザに名前と名前がまだレンダリングされていますが、データを1つの文字列としてレンダリングするVuexゲッターを作成します。 前述のように、VuexゲッターはVuexストアの計算されたプロパティと考えることができます。
ゲッターを作成するには、選択したテキストエディターでsrc/store/index.js
ファイルを開きます。 開いたら、関数を値としてgetters
オブジェクトにプロパティを作成します。 プロパティの名前は、後でゲッターにアクセスする方法です。
次の強調表示されたコードを追加します。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' export default createStore({ state: { firstName: 'John', lastName: 'Doe' }, ... getters: { fullName: function () { } } })
この場合、関数を使用して名前と名前を組み合わせ、結果のプロパティをfullName
として保存します。 関数内で、Vuexストア内にあるstate
オブジェクトを渡す必要があります。 そこから、名前と名前が補間された文字列を返します。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' export default createStore({ state: { firstName: 'John', lastName: 'Doe' }, ... getters: { fullName: function (state) { return `${state.firstName} ${state.lastName}` } } })
ここでは、テンプレートリテラルを使用して、firstName
とlastName
を1つの文字列にまとめています。
このファイルを保存して、App.vue
に戻ります。 このファイルで、最初と最後の値を削除し、それらをゲッターに置き換えます。
お気に入り-airports/src / App.vue
<template> <div class="wrapper"> <p>{{ $store.getters.fullName }}</p> <div v-for="airport in airports" :key="airport.abbreviation"> <airport-card :airport="airport" /> </div> </div> </template> ...
この変更を行ってファイルを保存すると、ブラウザはホットリロードします。 以前と同じようにブラウザに名前と名前が表示されますが、現在はゲッターを利用しています。 Vuexストアの名前の1つを変更すると、ゲッターは自動的に更新されます。
ゲッターから進んで、actions
があります。 最後のステップで述べたように、このチュートリアルでは、データを直接変更するのではなく、常にアクションを使用します。
このプロジェクトでは、ユーザーがカードをクリックしたときに、空港のデータを「お気に入り」リストに追加します。 最初にアクションとミューテーションを作成し、後でv-on
ディレクティブを使用してクリックイベントに割り当てます。
アクションを作成するには、テキストエディタでsrc/store/index.js
ファイルを開きます。 ストアのactions
セクションで、関数を作成します。 getter
と同様に、関数名は後でアクションを参照する方法になります。 この関数にaddToFavorites
という名前を付けます。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' export default createStore({ state: { firstName: 'John', lastName: 'Doe', favorites: [] // will store favorites here }, mutations: { }, actions: { addToFavorites() { } }, getters: { fullName: function (state) { return `${state.firstName} ${state.lastName}` } } })
アクションは、context
(Vueアプリ自体)とpayload
(ストアに追加するデータ)の2つの引数を受け入れます。 コンテキストにはcommit
メソッドが関連付けられており、後で作成するミューテーションを呼び出すために使用します。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' export default createStore({ state: { firstName: 'John', lastName: 'Doe', favorites: [] }, mutations: { }, actions: { addToFavorites(context, payload) { context.commit('UPDATE_FAVORITES', payload) } }, getters: { fullName: function (state) { return `${state.firstName} ${state.lastName}` } } })
commit
メソッドは、呼び出すミューテーションの名前とpayload
またはミューテーションが状態を置き換えるデータの2つの引数も受け入れます。
このコードでは、ミューテーションにUPDATE_FAVORITES
という名前を付けています。 ミューテーション名は不可知論的であり、特定のアクションにちなんで名付けられてはなりません。 たとえば、ADD_FAVORITE
やREMOVE_FAVORITE
のような変更は、データの一部を削除または追加するなどのロジックを意味します。 ミューテーションには1つのジョブと1つのジョブのみが必要であるため、これは理想的ではありません。状態を更新します。 データの追加と削除を区別するために、2つの異なるactions
を使用して、お気に入りの空港をアレイから削除または追加し、UPDATE_FAVORITES
という単一のミューテーションを実行して、アレイを更新します。渡されました。 ストア内のミューテーションの量を最小限に抑えると、Vuexストアの複雑さとサイズが大きくなるため、管理が容易になります。
次に、このアクションにロジックを追加します。 空港を「お気に入り」として追加する場合、そのペイロード(空港データ)を既存のアレイに追加します。 これを行うには、JavaScriptでpushメソッドを使用できます。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' export default createStore({ state: { firstName: 'John', lastName: 'Doe', favorites: [] }, mutations: { }, actions: { addToFavorites(context, payload) { const favorites = context.state.favorites favorites.push(payload) context.commit('UPDATE_FAVORITES', favorites) } }, getters: { fullName: function (state) { return `${state.firstName} ${state.lastName}` } } })
この時点で、payload
をfavorites
配列に追加し、変更された配列を新しいデータとして変更を呼び出すようにアクションが設定されています。 次に、UPDATE_FAVORITES
ミューテーションを定義します。 次のコードを追加して、favorites
アレイを新しいアレイとして設定します。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' export default createStore({ state: { firstName: 'John', lastName: 'Doe', favorites: [] }, mutations: { UPDATE_FAVORITES(state, payload) { state.favorites = payload } }, actions: { addToFavorites(context, payload) { const favorites = context.state.favorites favorites.push(payload) context.commit('UPDATE_FAVORITES', favorites) } }, getters: { fullName: function (state) { return `${state.firstName} ${state.lastName}` } } })
アクションとミューテーションができたので、このファイルを保存できます。
このアクションを実行するには、ユーザーがカードをクリックしたときにdispatch
イベントを呼び出すことができます。 これは、v-on
ディレクティブを使用して行います。
テキストエディタでApp.vue
ファイルを開きます。 <airport-card />
コンポーネントで、v-on
ディレクティブの短縮構文(@
)を追加し、イベントをclick
にします。
お気に入り-airports/src / App.vue
<template> <div class="wrapper"> <p>{{ $store.getters.fullName }}</p> <div v-for="airport in airports" :key="airport.abbreviation"> <airport-card :airport="airport" @click="$store.dispatch('addToFavorites', airport)" /> </div> <h2 v-if="$store.state.favorites.length">Favorites</h2> <div v-for="airport in $store.state.favorites" :key="airport.abbreviation"> <airport-card :airport="airport" /> </div> </div> </template> ...
dispatch
関数は、アクション名とアクションに送信するペイロードデータの2つの引数を受け入れます。
このファイルを保存して、ブラウザで開きます。 これで、空港カードをクリックすると、アクションによってミューテーションが呼び出され、状態が更新され、空港がお気に入りのプロパティに追加されます。
このステップでは、前に作成したVuexストアを拡張しました。 配列をコピーし、その配列に新しいアイテムをプッシュするアクションを作成しました。 そのアクションはミューテーションと呼ばれ、状態を更新しました。 それに加えて、getters
と、それらを活用してVuexストアの読み取り専用値を組み合わせたり変更したりして新しいプロパティを作成する方法について学びました。
最後のステップでは、Vuexモジュールを実装します。 モジュールは、Vuexストアをより小さなVuexストアに分割するための優れた方法です。 これは、Vuexストアの栽培者のサイズと複雑さが大きくなる場合に役立ちます。
ステップ4—Vuexモジュールの作成
モジュールは、単一のVuexストアに結合された小さなVuexストアです。 これは、複数のVue.jsコンポーネントがApp.vue
などの単一の.vue
ファイルにインポートされる方法と似ています。 このステップでは、このVuexストアを2つの別々のモジュールに分割します。 1つのモジュールはuser
状態用で、もう1つはairport
状態、アクション、およびミューテーションに固有です。
ターミナルで、cd
をstore
ディレクトリに移動し、touch
コマンドを使用して2つの別々のファイルを作成します。
touch src/store/user.module.js touch src/store/airports.module.js
user.module.js
ファイル内に、次のコードを追加して、デフォルトでエクスポートされるオブジェクトを作成します。
お気に入り-airports/src / store / user.module.js
export default { namespaced: true }
また、プロパティnamespaced
を追加し、その値をtrue
とします。 namespace
プロパティを使用すると、後でドット表記のプロパティにアクセスするときにモジュール名を参照できるようになります。
このオブジェクト内に、ユーザーに関連付けられているstate
およびgetter
情報を追加します。
お気に入り-airports/src / store / user.module.js
export default { namespaced: true, state: { firstName: 'John', lastName: 'Doe' }, getters: { fullName: function (state) { return `${state.firstName} ${state.lastName}` } } }
ユーザーモジュールには、ユーザー情報に必要なすべてのものが含まれています。 ファイルを保存して終了します。
先に進み、airports.module.js
ファイルで同じことを行います。 テキストエディタでairports.module.js
ファイルを開き、次を追加します。
お気に入り-airports/src / store / airports.module.js
export default { state: { favorites: [] }, mutations: { UPDATE_FAVORITES(state, payload) { state.favorites = payload } }, actions: { addToFavorites(context, payload) { const favorites = context.state.favorites favorites.push(payload) context.commit('UPDATE_FAVORITES', favorites) } }, }
airport
関連のミューテーション、アクション、および状態を設定したので、airports.module.js
を保存できます。
次に、これら2つのファイルをメインのstore/index.js
ファイルにimport
します。 テキストエディタで、store/index.js
ファイルを開き、state
、mutations
、actions
、およびgetters
プロパティを削除します。 ファイルは次のスニペットのようになります。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' export default createStore({ })
モジュールを登録するには、次の強調表示されたコードを使用して、モジュールをこのindex.js
ファイルにインポートする必要があります。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' import UserModule from './user.module.js' import AirportsModule from './airports.module.js' export default createStore({ })
ここから、値としてオブジェクトを持つmodules
というプロパティが必要になります。 このオブジェクト内のプロパティ名は、Vuexモジュールの名前になります。 モジュール名の値は、インポートされたモジュール自体です。
お気に入り-airports/src / store / index.js
import { createStore } from 'vuex' import UserModule from './user.module.js' import AirportsModule from './airports.module.js' export default createStore({ modules: { user: UserModule, airports: AirportsModule } })
このファイルを保存すると、モジュールが登録され、単一のVuexストアに結合されます。 store/index.js
を保存し、App.vue
ファイルを開いて更新し、新しく作成されたモジュールを参照します。
お気に入り-airports/src / App.vue
<template> <div class="wrapper"> <p>{{ $store.getters['user/fullName'] }}</p> <div v-for="airport in airports" :key="airport.abbreviation"> <airport-card :airport="airport" @click="$store.dispatch('addToFavorites', airport)" /> </div> <h2 v-if="$store.state.airports.favorites.length">Favorites</h2> <div v-for="airport in $store.state.airports.favorites" :key="airport.abbreviation"> <airport-card :airport="airport" /> </div> </div> </template> ...
これで、Vuexセットアップのモジュラーバージョンができました。
このステップでは、既存のVuexストアをモジュールと呼ばれる小さなチャンクにセグメント化しました。 これらのモジュールは、関連するストアのプロパティを小さなVuexストアにグループ化するための優れた方法です。 また、App.vue
を更新して、各モジュールの状態とディスパッチイベントを参照しました。
結論
大まかに言えば、状態管理はデータの更新がすべてです。 この設定では、状態のデータはアプリケーション全体でグローバルであり、信頼できる唯一の情報源として機能します。これは、アクションとミューテーションの形式の明示的な関数でのみ更新できます。 このチュートリアルでは、state
、mutations
、actions
、およびgetters
の例を実行し、これらの各プロパティがどのように独自の目的を持っているかを確認しました。更新サイクル。
Vuex、アクション、ミューテーション、およびモジュールの詳細については、Vue.jsコアチームによって作成された公式Vuexドキュメントを確認してください。 Vueのその他のチュートリアルについては、Vue.jsシリーズページを使用してWebサイトを開発する方法を確認してください。