SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

TypeScriptで学ぶJavaScriptフレームワーク「Vue.js」の利用法

TypeScriptとも相性抜群なライブラリ──Vue.jsで状態管理を行う新定番「Pinia」を解説!

TypeScriptで学ぶJavaScriptフレームワーク「Vue.js」の利用法 第8回

  • X ポスト
  • このエントリーをはてなブックマークに追加

 本連載では、JavaScriptフレームワーク「Vue.js」を、型定義が利用できるようJavaScriptを拡張した言語「TypeScript」で活用する方法を、順を追って説明していきます。前回は複数のコンポーネントをURLによって切り替え表示できる「Vue Router」の利用法を説明しました。今回はVue.jsの状態管理ライブラリ「Pinia」について説明します。

  • X ポスト
  • このエントリーをはてなブックマークに追加

はじめに

 本連載では、JavaScriptを利用して動的なWebページを構築できるフレームワークVue.jsを、データの型定義ができるように拡張されたAltJS(コンパイルしてJavaScriptにする言語)であるTypeScriptで活用する方法を、順を追って説明しています。

 一般にWebページは、ユーザーの入力値やWeb APIから取得したデータなど、さまざまな状態を持ちます。これらの状態がさまざまなコンポーネントに散在すると管理が困難になるため、Webページ全体で単一の状態を共有して管理することが望ましいと言われています。Vue.jsには、このような状態管理を行うライブラリーとしてVuexがありますが、今回紹介するPiniaは、Vuexの代替として利用できる状態管理ライブラリーです。よりシンプルな利用方法や、TypeScriptへのネイティブ対応などのメリットがあります。

図1 Piniaの公式ページ
図1 Piniaの公式ページ

 本記事では、Vue.jsのWebページでPiniaを利用して状態管理を行う方法を、サンプルコードとともに説明していきます。

対象読者

  • これからVue.jsに入門したい方
  • Webページ全体の状態管理をシンプルに行いたい方
  • Vuexが複雑で難しいと感じていた方

必要な環境

 本記事のサンプルコードは、以下の環境で動作を確認しています。

  • Windows 10 64bit版
    • Node.js v20.9.0 64bit版
    • Vue.js 3.3.7
    • Pinia 2.1.7
    • Vuex 4.0.2(Piniaとの比較用)
    • TypeScript 5.2.2
    • Microsoft Edge 119.0.2151.58

 サンプルコードを実行するには、サンプルのフォルダーで「npm install」コマンドを実行してライブラリーをダウンロード後、「npm run dev」コマンドを実行して、Webブラウザーで「http://localhost:5173/」を表示します。

Pinia対応のプロジェクトを生成して動作させる

 Vue.jsのプロジェクトを生成時に実行する「npm init vue@latest」コマンドでは、状態管理のライブラリーとして(Vuexではなく)Piniaをプロジェクトに含めることができます。対話的に表示される「Add Pinia for state management?」に「Yes」と回答します。本記事ではTypeScriptを利用するので「Add TypeScript?」も「Yes」と回答します。

図2 PiniaとTypeScriptを有効にしてプロジェクトを生成(p001-basic)
図2 PiniaとTypeScriptを有効にしてプロジェクトを生成(p001-basic)

生成したプロジェクトに含まれるPiniaの実装をチェック

 生成されたプロジェクトには、Webページの初期化コードでPiniaを有効にする処理と、状態を格納する「ストア」の実装が含まれます。初期化コード(src/main.ts)はリスト1の通りです。(1)のapp.useメソッドに、createPinia関数の戻り値を渡して実行することで、Vue.jsのWebページでPiniaを利用できるようになります。

[リスト1]Piniaの使用を指定する記述(p001-basic/src/main.ts)
const app = createApp(App)  // アプリ生成
app.use(createPinia())      // Piniaの使用を指定 ...(1)
app.mount('#app')           // アプリをマウント(表示)

 次に、ストアの実装をリスト2に示します。

[リスト2]状態を格納するストアの実装(p001-basic/src/stores/counter.ts)
export const useCounterStore = defineStore('counter', () => {
  // ステート ...(1)
  const count = ref(0)
  // ゲッター ...(2)
  const doubleCount = computed(() => count.value * 2)
  // アクション ...(3)
  function increment() {
    count.value++
  }
  // 定義したステート、ゲッター、アクションを返却 ...(4)
  return { count, doubleCount, increment }
})

 defineStoreメソッドの第1引数にストアを識別するID、第2引数にストアの内容を返却する関数を指定して、ストアを取得するuseCounterStore関数を定義します。第2引数に指定するストアの内容には表1の内容を定義して、(4)でreturnします。

表1 ストアに定義する内容
No. 項目 意味 リスト2での定義内容
(1) ステート ストアで管理する状態 count(カウンターの数値)
(2) ゲッター ステートをもとに返却する値 doubleCount(countの2倍)
(3) アクション ストアに対して行う操作 increment(countを1増やす)

[補足]Setup StoresとOption Stores

 リスト2のストア記述方法は「Setup Stores」と呼ばれ、Composition APIのコンポーネントで利用するsetup関数と記述方法が類似しています。ステートはコンポーネントのデータ、ゲッターは算出プロパティ、アクションはメソッドに、それぞれ対応します。

 Setup Storesに対して、Options APIのコンポーネント記述法に類似した「Option Stores」を利用することもできます。リスト2と同じストアをOption Storesで記述すると、リスト3の通りになります。実装の詳細はp002-option-storesサンプルを参照してください。

[リスト3]Option Storesの記述例(p002-option-stores/src/stores/counter.ts)
export const useCounterStore = defineStore('counter', {
  // ステート
  state() {
    return {
      count : 0
    }
  },
  // ゲッター
  getters: {
    doubleCount: (state) => state.count * 2
  },
  // アクション
  actions : {
    increment() {
      this.count++
    }
  }
})

生成したプロジェクトに実装を追加してPiniaを動作させる

 CLIツールで生成させたプロジェクトには、Piniaの初期化処理(リスト1)とストア(リスト2)が含まれますが、ストアを利用する処理は含まれません。そこで、生成したプロジェクトに実装を追加して、Piniaを動作させる図3のサンプルを作っていきます。ストアのcountステートとdoubleCountゲッターの値が画面に表示され、ボタンをクリックするごとにcountが1ずつ増えていき、doubleCountはcountの2倍の値が表示されます。

図3 生成されたプロジェクトに含まれるPiniaを動作させるサンプル(p001-basic)
図3 生成されたプロジェクトに含まれるPiniaを動作させるサンプル(p001-basic)

 Webページ全体に対応するAppコンポーネントには、ストアを表示するShowStoreコンポーネントと、状態を更新するMutateStateコンポーネントを含めるようにします(詳細はサンプルコードを参照)。表示と更新でコンポーネントを分けるのは、コンポーネントをまたいで状態が共有されることを示すためです。

 ShowStoreコンポーネントの実装はリスト4の通りです。<script>部の(2)で、リスト2のcounter.tsからインポートしたuseCounterStore関数を実行してストアを取得し、<template>部の(1)でストアのcountステートとdoubleCountゲッターを画面に表示します。

[リスト4]ShowStoreコンポーネントの実装(p001-basic/src/components/ShowStore.vue)
<template>
  <div class="component">
    <!-- ストアの内容を表示 ...(1)-->
    <div>State(count):{{ store.count }}</div>
    <div>Getter(doubleCount):{{ store.doubleCount }}</div>
  </div>
</template>
<script setup lang="ts">
// ストアを取得 ...(2)
import { useCounterStore } from '../stores/counter'
const store = useCounterStore()
</script>

 一方、MutateStateコンポーネントの<script>部はリスト5の通りです。(1)でストアを取得し、ボタンクリック時の処理(2)で、ストアのincrementアクションを実行してカウンターを1増やします(3)。

[リスト5]MutateStateコンポーネントの実装(p001-basic/src/components/MutateState.vue)
// ストアを取得 ...(1)
import { useCounterStore } from '../stores/counter'
const store = useCounterStore()
// カウンター追加ボタンの処理 ...(2)
function onClickButtonIncrement() {
  // ストアのincrementアクションを実行 ...(3)
  store.increment()
}

 ShowStoreコンポーネント(リスト4)とMutateStateコンポーネント(リスト5)は、それぞれ別個にストアを取得していますが、Piniaの仕組みにより、これらのストアは単一の状態を共有するため、MutateStateコンポーネントでincrementアクションを実行すると、ストアのカウンターが増加して、ShowStoreコンポーネント画面表示に反映されます。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
VuexとPiniaとの比較

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
TypeScriptで学ぶJavaScriptフレームワーク「Vue.js」の利用法連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/18727 2023/12/11 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング