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
ファイルを作成し、以下を追加します。
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
ターミナルに戻ります。
その手順を完了したら、次の名前の単一ファイルコンポーネント(SFC)を作成します。 AirportCard.vue
. このファイルは components
プロジェクトのディレクトリ。 このコンポーネントには、エアポートカードのすべてのスタイルとロジックが含まれます。 ターミナルで、 .vue
を使用してファイル touch
指図:
- touch src/components/AirportCard.vue
開ける 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にスタイルを追加します。 The :first-child
と :last-child
最初と最後に異なるスタイルを適用する疑似セレクターです p
内部のHTMLのタグ div
のクラスで airport
. それに加えて、このコンポーネントには prop が含まれていることに気付くかもしれません。これは、Vue.jsでは親コンポーネントから子コンポーネントにデータを渡す方法です。
ファイルを保存して終了します。
セットアップを完了する前に、既存のものを交換してください 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
データと一連のレンダリング AirportCards.vue
小道具を介して渡された空港データを含むコンポーネント :airport
. このコードを保存して、コマンドラインに戻ります。
プロジェクトを設定したら、を使用してローカル開発サーバーを実行します。 npm run serve
ターミナルのコマンド:
- npm run serve
これにより、サーバーが起動します localhost
、通常は港で 8080
. 選択したWebブラウザを開き、次の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ストアを初期化します。 これを行うには、を活用する必要があります createStore
Vuexの関数:
import { createStore } from 'vuex'
export default createStore({
})
あなたも export
これは、後でインポートするためです。 main.js
ファイル。
この時点で、Vuexストアがセットアップされていますが、アプリケーションはまだVuexストアまたはその使用方法を認識していません。 ストアを完全に初期化するには、 import
それをあなたに main.js
ファイル。 テキストエディタで、 src/main.js
ファイル。
直後 createApp(App)
、チェーン use
次の強調表示されたコードに示すように、メソッドを作成して、インポートするストアに渡します。
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
createApp(App).use(store).mount('#app')
チェーンしたら use
メソッド、このファイルを保存します。 The use
メソッドは、アプリケーションのビルド時にどのコードをバンドルするかをVueアプリケーションに指示します。 この場合、Vuexストアを「使用」またはバンドルするようにVueに指示しています。
次のセクションに進む前に、状態の値をストアに追加し、 App.vue
ファイル。 あなたの 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
テキストエディタでファイルを作成し、以下を追加します。
<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>
...
The $store
この場合は、で初期化したグローバルストアです。 main.js
ファイル。 ログに記録する場合 this.$store
コンソールに、あなたは店を見るでしょう object
. そこから、コードはドット表記を介して表示するプロパティにアクセスします。
保存 App.vue
次に、Webブラウザを開きます。 空港カードの上に、Vuexストアに保存した名前と名前が表示されます。 これらはのデフォルト値です firstName
と lastName
、 それぞれ。
このステップでは、Vuexをインストールし、Vuexストアを作成しました。 いくつかのデフォルトのストアデータを追加し、それをビューに表示しました $store
ドット概念を使用したオブジェクト。 次のステップでは、Vuexストアを次の方法で更新します。 actions
と mutations
、およびで結合されたデータを取得します getters
.
ステップ3—アクション、ミューテーション、およびゲッターを作成する
ステップ2では、Vuexを手動でインストールし、プロジェクトに統合しました。 このステップでは、ブラウザに名前と名前がまだレンダリングされていますが、データを1つの文字列としてレンダリングするVuexゲッターを作成します。 前述のように、VuexゲッターはVuexストアの計算されたプロパティと考えることができます。
ゲッターを作成するには、 src/store/index.js
選択したテキストエディタでファイルを作成します。 開いたら、にプロパティを作成します getters
関数を値として持つオブジェクト。 プロパティの名前は、後でゲッターにアクセスする方法です。
次の強調表示されたコードを追加します。
import { createStore } from 'vuex'
export default createStore({
state: {
firstName: 'John',
lastName: 'Doe'
},
...
getters: {
fullName: function () {
}
}
})
この場合、関数を使用して名前と名前を組み合わせ、結果のプロパティを次のように格納します。 fullName
. 関数内で、を渡す必要があります state
Vuexストア内にあるオブジェクト。 そこから、名前と名前が補間された文字列を返します。
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
. このファイルで、最初と最後の値を削除し、それらをゲッターに置き換えます。
<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
:
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}`
}
}
})
アクションは2つの引数を受け入れます: context
、またはVueアプリ自体、および payload
、またはストアに追加するデータ。 コンテキストには commit
後で作成するミューテーションを呼び出すために使用する、それに関連付けられたメソッド:
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}`
}
}
})
The commit
メソッドは2つの引数も受け入れます:呼び出すミューテーションの名前と payload
または、突然変異によって状態が置き換えられるデータ。
このコードでは、ミューテーションに名前を付けています UPDATE_FAVORITES
. ミューテーション名は不可知論的であり、特定のアクションにちなんで名付けられてはなりません。 たとえば、次のような突然変異 ADD_FAVORITE
と REMOVE_FAVORITE
データの一部を削除または追加するようなロジックを意味します。 ミューテーションには1つのジョブと1つのジョブのみが必要であるため、これは理想的ではありません。状態を更新します。 データの追加と削除を区別するために、2つの異なるものを使用できます actions
アレイからお気に入りの空港を削除または追加し、次のような単一のミューテーションを実行します。 UPDATE_FAVORITES
渡されたもので配列を更新します。 ストア内のミューテーションの量を最小限に抑えると、Vuexストアの複雑さとサイズが大きくなるため、管理が容易になります。
次に、このアクションにロジックを追加します。 空港を「お気に入り」として追加する場合、そのペイロード(空港データ)を既存のアレイに追加します。 これを行うには、JavaScriptでpushメソッドを使用できます。
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
新しい配列としての配列:
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
:
<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>
...
The dispatch
関数は、アクション名とアクションに送信するペイロードデータの2つの引数を受け入れます。
このファイルを保存して、ブラウザで開きます。 これで、空港カードをクリックすると、アクションによってミューテーションが呼び出され、状態が更新され、空港がお気に入りのプロパティに追加されます。
このステップでは、前に作成したVuexストアを拡張しました。 配列をコピーし、その配列に新しいアイテムをプッシュするアクションを作成しました。 そのアクションはミューテーションと呼ばれ、状態を更新しました。 それに加えて、あなたはについて学びました getters
また、Vuexストアの読み取り専用値を組み合わせたり変更したりすることで、それらを活用して新しいプロパティを作成する方法について説明します。
最後のステップでは、Vuexモジュールを実装します。 モジュールは、Vuexストアをより小さなVuexストアに分割するための優れた方法です。 これは、Vuexストアの栽培者のサイズと複雑さが大きくなる場合に役立ちます。
ステップ4—Vuexモジュールの作成
モジュールは、単一のVuexストアに結合された小さなVuexストアです。 これは、複数のVue.jsコンポーネントを1つのコンポーネントにインポートする方法と似ています。 .vue
などのファイル App.vue
. このステップでは、このVuexストアを2つの別々のモジュールに分割します。 1つのモジュールは user
状態、および他はに固有になります airport
状態、アクション、および突然変異。
あなたのターミナルでは、 cd
に store
ディレクトリを使用し、 touch
2つの別々のファイルを作成するコマンド。
- touch src/store/user.module.js
- touch src/store/airports.module.js
の内部 user.module.js
ファイルに、次のコードを追加して、デフォルトでエクスポートされるオブジェクトを作成します。
export default {
namespaced: true
}
プロパティも追加しています namespaced
その値は true
. The namespace
プロパティはそれを作成するので、後でドット表記でプロパティにアクセスするときにモジュール名を参照できます。
このオブジェクトの中に、 state
と getter
ユーザーに関連付けられている情報:
export default {
namespaced: true,
state: {
firstName: 'John',
lastName: 'Doe'
},
getters: {
fullName: function (state) {
return `${state.firstName} ${state.lastName}`
}
}
}
ユーザーモジュールには、ユーザー情報に必要なすべてのものが含まれています。 ファイルを保存して終了します。
先に進み、同じことをします airports.module.js
ファイル。 を開きます 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
.
次、 import
これらの2つのファイルをメインに store/index.js
ファイル。 テキストエディタで、 store/index.js
ファイルを削除し、 state
, mutations
, actions
、 と getters
プロパティ。 ファイルは次のスニペットのようになります。
import { createStore } from 'vuex'
export default createStore({
})
モジュールを登録するには、モジュールをこれにインポートする必要があります index.js
次の強調表示されたコードを含むファイル:
import { createStore } from 'vuex'
import UserModule from './user.module.js'
import AirportsModule from './airports.module.js'
export default createStore({
})
ここから、というプロパティが必要になります modules
値としてオブジェクトを使用します。 このオブジェクト内のプロパティ名は、Vuexモジュールの名前になります。 モジュール名の値は、インポートされたモジュール自体です。
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
ファイルを更新し、新しく作成されたモジュールを参照するように更新します。
<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サイトを開発する方法を確認してください。