著者は、 Write for DOnations プログラムの一環として、 Open Sourcing MentalIllnessを選択して寄付を受け取りました。

序章

Vuex は、Vue.js用のファーストパーティの開発状態管理ライブラリです。 これはEvanYouによって作成され、現在Vue.jsコアチームによって維持されています。 他の多くの状態管理ライブラリと同様に、Vuexは、 Redux が過去数年にわたって普及してきた原則に従います。データは一方向に流れ、アクションとミューテーションによって、ストアと呼ばれる信頼できる唯一の情報源のデータが変更されます。

Vuex store は、さまざまなメソッドとデータのコレクションです。 操作などのこれらのメソッドの一部は、データがミューテーションに送信される前にデータをフェッチして処理できます。 mutation は、提供された値でストアプロパティを変更または更新するメソッドです。 Getters は、データを変更または結合して新しい状態プロパティを作成できるメソッドです。 これらのゲッターは読み取り専用であり、データを変更しません。 これらは、Vue.jsコンポーネントの計算されたプロパティに似ています。 Vuexの最後のコンポーネントは、 state 、または信頼できる唯一の情報源として機能するデータセットです。

このチュートリアルでは、空港情報を含むカードのリストをレンダリングするアプリケーションを作成します。 クリックすると、これらのカードはVuexワークフローを実行して、選択した空港をお気に入りのリストに追加します。 この例を実行することにより、状態を管理するためのアクションとミューテーションを作成し、計算されたデータを取得するためのゲッターを作成します。

前提条件

ステップ1—サンプルアプリケーションのセットアップ

Vuexで状態がどのように管理されているかを視覚化するために、ビューに表示するデータを使用してプロジェクトを設定します。 このプロジェクトとチュートリアル全体で使用します。

一度 favorite-airports プロジェクトは、前提条件セクションの説明に従って作成され、このプロジェクトのすべてのローカルデータを保持するディレクトリを作成します。 ターミナルを開き、プロジェクトのルートディレクトリで次のコマンドを実行します(favorite-airports):

  1. mkdir src/data
  2. 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 ターミナルに戻ります。

その手順を完了したら、次の名前の単一ファイルコンポーネント(SFC)を作成します。 AirportCard.vue. このファイルは components プロジェクトのディレクトリ。 このコンポーネントには、エアポートカードのすべてのスタイルとロジックが含まれます。 ターミナルで、 .vue を使用してファイル touch 指図:

  1. 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にスタイルを追加します。 The :first-child:last-child 最初と最後に異なるスタイルを適用する疑似セレクターです p 内部のHTMLのタグ div のクラスで 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 データと一連のレンダリング AirportCards.vue 小道具を介して渡された空港データを含むコンポーネント :airport. このコードを保存して、コマンドラインに戻ります。

プロジェクトを設定したら、を使用してローカル開発サーバーを実行します。 npm run serve ターミナルのコマンド:

  1. npm run serve

これにより、サーバーが起動します localhost、通常は港で 8080. 選択したWebブラウザを開き、次のWebサイトにアクセスします。 localhost:8080以下を参照してください。

サンプルアプリケーションがセットアップされたので、次のステップでVuexライブラリをインストールして作成します。 store. このストアは、状態、ミューテーション、アクション、ゲッターなど、さまざまなVuexアイテムのコレクションです。 これを説明するために、ディスパッチメソッドを実行します。これにより、アプリのお気に入りセクションに空港が追加されます。

ステップ2—Vuexをインストールする

Webベースのアプリケーションで作業する場合、多くの場合、stateで作業します。 状態は、特定の時点でのデータのコレクションです。 この状態は、ユーザーの操作によって変更できます。 dispatchcommit メソッド。 ユーザーがデータを変更すると、ディスパッチイベントが実行され、データが mutation に渡され、 state 物体。

状態の更新にアプローチする方法はいくつかあります。 一部の開発者はスキップします actions まっすぐに行きます mutatations. ただし、このチュートリアルのために、常に実行します action それは順番に mutation. このようにして、アクション内に複数のミューテーションを含めることができます。 Vuexの基本的なルールは、ミューテーションには1つのジョブと1つのジョブのみがあるということです。ストアを更新します。 アクションは、データの結合、データのフェッチ、JavaScriptロジックの実行など、さまざまなことを実行できます。

アクションに加えて、gettersもあります。 ゲッターは、複数の状態値を1つの値に結合する方法です。 Vue.jsの計算されたプロパティに精通している場合、ゲッターは状態固有の計算されたプロパティと考えることができます。

Vuexの用語をカバーしたら、Vuexのインストールと統合を開始します。 ターミナルを開き、次のコマンドを実行します。

  1. npm install vuex@next --save

このコマンドは、Vue.js 3.xと最も互換性のあるバージョンのVuexをインストールし、 package.json ファイル。 次に、ストアのディレクトリとインデックスファイルを作成します。 を使用します mkdir ディレクトリを作成するコマンドと touch 新しいファイルを作成するには:

  1. mkdir src/store
  2. touch src/store/index.js

テキストエディタを開き、 store/index.js ファイル、Vuexストアを初期化します。 これを行うには、を活用する必要があります createStore Vuexの関数:

空港-favorites/src / store / index.js
import { createStore } from 'vuex'

export default createStore({
  
})

あなたも export これは、後でインポートするためです。 main.js ファイル。

この時点で、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 メソッド、このファイルを保存します。 The 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>
...

The $store この場合は、で初期化したグローバルストアです。 main.js ファイル。 ログに記録する場合 this.$store コンソールに、あなたは店を見るでしょう object. そこから、コードはドット表記を介して表示するプロパティにアクセスします。

保存 App.vue 次に、Webブラウザを開きます。 空港カードの上に、Vuexストアに保存した名前と名前が表示されます。 これらはのデフォルト値です firstNamelastName、 それぞれ。

このステップでは、Vuexをインストールし、Vuexストアを作成しました。 いくつかのデフォルトのストアデータを追加し、それをビューに表示しました $store ドット概念を使用したオブジェクト。 次のステップでは、Vuexストアを次の方法で更新します。 actionsmutations、およびで結合されたデータを取得します 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. 関数内で、を渡す必要があります state Vuexストア内にあるオブジェクト。 そこから、名前と名前が補間された文字列を返します。

お気に入り-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}`
    }
  }
})

ここではテンプレートリテラルを使用して firstNamelastName 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}`
    }
}
})

アクションは2つの引数を受け入れます: context、またはVueアプリ自体、および payload、またはストアに追加するデータ。 コンテキストには 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}`
    }
 }
})

The commit メソッドは2つの引数も受け入れます:呼び出すミューテーションの名前と payload または、突然変異によって状態が置き換えられるデータ。

このコードでは、ミューテーションに名前を付けています UPDATE_FAVORITES. ミューテーション名は不可知論的であり、特定のアクションにちなんで名付けられてはなりません。 たとえば、次のような突然変異 ADD_FAVORITEREMOVE_FAVORITE データの一部を削除または追加するようなロジックを意味します。 ミューテーションには1つのジョブと1つのジョブのみが必要であるため、これは理想的ではありません。状態を更新します。 データの追加と削除を区別するために、2つの異なるものを使用できます actions アレイからお気に入りの空港を削除または追加し、次のような単一のミューテーションを実行します。 UPDATE_FAVORITES 渡されたもので配列を更新します。 ストア内のミューテーションの量を最小限に抑えると、Vuexストアの複雑さとサイズが大きくなるため、管理が容易になります。

次に、このアクションにロジックを追加します。 空港を「お気に入り」として追加する場合、そのペイロード(空港データ)を既存のアレイに追加します。 これを行うには、JavaScriptpushメソッドを使用できます。

お気に入り-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>
...

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 状態、アクション、および突然変異。

あなたのターミナルでは、 cdstore ディレクトリを使用し、 touch 2つの別々のファイルを作成するコマンド。

  1. touch src/store/user.module.js
  2. touch src/store/airports.module.js

の内部 user.module.js ファイルに、次のコードを追加して、デフォルトでエクスポートされるオブジェクトを作成します。

お気に入り-airports/src / store / user.module.js
export default {
  namespaced: true
}

プロパティも追加しています namespaced その値は true. The namespace プロパティはそれを作成するので、後でドット表記でプロパティにアクセスするときにモジュール名を参照できます。

このオブジェクトの中に、 stategetter ユーザーに関連付けられている情報:

お気に入り-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.

次、 import これらの2つのファイルをメインに store/index.js ファイル。 テキストエディタで、 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サイトを開発する方法を確認してください。