banner
isolcat

isolcat

I am not afraid of storms, for I am learning how to sail my ship
github

2k字で簡単に入門するPinia、猿でも理解できるチュートリアル

前言#

image.png

もう何年も経っているのに、まだ伝統的な状態管理ライブラリを使っているのですか?さあ、Piniaを学びましょう!

Pinia という名前の由来も面白いです。スペイン語で、Pinia はパイナップルという言葉の最も似た英語の発音です。そして、パイナップルは一組の個別の花が結合してできたもので、複数の果物を生み出します。これは stores に似ていて、それぞれが独立していますが、最終的にはつながりがあります。

私たちがvuexの github リポジトリを開くと、公式のメッセージPinia is now the new defaultが表示されます。Vue の次世代公式状態管理ライブラリとして、Pinia は多くの利点を持ち、Vuex が残した多くの問題を解決しています。書く際には、より論理的になります。それでは、少し理解してみましょう!

Pinia の利点#

  • vue3 と vue2 の両方をサポート
  • Mutation の操作を廃止し、stategetteractionのみ
  • Actionsは同期と非同期をサポート
  • プラグインを使用して Pinia の機能を拡張可能
  • モジュールのネストが不要で、Vue3 のComposition apiにより適合
  • TypeScript をサポート
  • コードがより簡潔

Pinia 方式でストアを作成#

まず、空のプロジェクトを素早く作成し、Piniaをインストールします:

npm install pinia

Pinia は vue2 をサポートしていますが、使用している vue のバージョンがVue2.7未満の場合は、composition api を独立してインストールする必要があります:@vue/composition-api(ここでは直接 Vue2.7 にアップグレードすることをお勧めします。Vue3 に比べて大きな違いはなく、Vue のエコシステムのサポートがより良くなります)

main.tsで Pinia をインポートします:

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'


const app = createApp(App)

app.use(createPinia())

app.mount('#app')

次に、src/storecounter.tsを作成し、基本テンプレートを書きます:

import { defineStore } from "pinia";

export const mainStore = defineStore('main', {
  state: () => {
    return {
      helloWord: 'HelloWorld'
    }
  },
  getters: {

  },
  actions: {

  }
})

mainStore(ストア名)を作成した後、コンポーネントで使用します。

<template>
  <div class="">{{ store.helloWord }}</div>
</template>

<script lang="ts" setup>
import { mainStore } from "../store/counter";
const store = mainStore();
</script>

<style scoped></style>

ページにhelloWorldが表示されれば、storeが正常に作成されたことを示します。

Pinia でデータ状態を変更#

counter.tsstateにデータcountを追加します:

import { defineStore } from "pinia";

export const mainStore = defineStore('main', {
  state: () => {
    return {
      count: 0,
      helloWord: 'HelloWorld'
    }
  },
  getters: {

  },
  actions: {

  }
})

クリックイベントボタンを作成します:

<template>
  <div>
    <button @click="handleClick">データ状態を変更</button>
  </div>
</template>

<script setup lang="ts">
import { mainStore } from "@/stores/counter";
const store = mainStore();
const handleClick = () => {
  store.count++;
};
</script>

これをApp.vueにインポートし、データ状態を変更します:

<template>
  <Click />
  <CountButton />
</template>

<script lang="ts" setup>
import Click from "./components/Click.vue";
import CountButton from "./components/CountButton.vue";
</script>

この時、ボタンをクリックするとcountの値が変更されることがわかります。

実際の開発では、storeのデータを何度も呼び出す必要があることが多いです。毎回その値を変更するために{{store.****}}を使うのは面倒なので、解構します:

<template>
  <div class="">{{ store.helloWord }}</div>
  <div class="">{{ store.count }}</div>
  <hr />
  <!-- 解構後はstoreを省略でき、コード量が減ります -->
  <div>{{ helloWord }}</div>
  <div>{{ count }}</div>
</template>

<script lang="ts" setup>
import { mainStore } from "../store/counter";
import { storeToRefs } from "pinia";
const store = mainStore();

// 解構を行う
const { helloWord, count } = storeToRefs(store);
</script>

<style scoped></style>

注意:解構にはstoreToRefs()関数を使用する必要があります!

Pinia でデータを変更する 4 つの方法#

  • 第一の方法:
const handleClick = () => {
  store.count++;
};
  • 第二の方法$patch
const handleClickPatch=()=>{
	store.$patch({
		count:store.count+2
	})
}

第二の方法は第一の方法ほど簡単ではありませんが、複数のデータの変更により適しています。

  • 第三の方法 $patchに関数を渡す
const handleClickMethod = () => {
  // ここでのstateはストアのstateを指します
  store.$patch((state) => {
    state.count++;
    state.helloWord = state.helloWord === "jspang" ? "Hello World" : "jspang";
  });
};
  • 第四の方法 action

ビジネスロジックが非常に複雑な場合は、メソッドをstoreactionに書きます。

actions: {
    changeState() {
      this.count++
      this.helloWord = 'jspang'
    }
  }

Getters#

vuex の getters とほぼ同じで、vue の計算プロパティに相当します。しかし、vuex のドキュメントを確認すると、次のような注意書きがあります:

注意

Vue 3.0 以降、getter の結果は計算プロパティのようにキャッシュされなくなりました。これは既知の問題で、3.1 バージョンで修正される予定です。詳細は PR #1878をご覧ください。

今でもこの注意書きは存在しており、これが私がPiniaを使用することをより推奨する理由の一つです。

Pinia のGettersは内部でキャッシュが可能であることをコードで確認します:

getters: {
    phoneHidden(state) {
      // 正規表現
      console.log('gettersが呼び出されました');
      return state.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2')
    }
  },

コンポーネント内で phone(データ)を 2 回呼び出し、コンソールを開いて確認します。

image.png

1 回だけ表示されることが確認でき、キャッシュ機能があることが証明されました。これはパフォーマンスの最適化に役立ちます。

Pinia の stores 相互呼び出し#

実際の開発では、通常 1 つのストアだけを使用することはありません。ストア同士は通常、調整があります。ここで新しいストアを作成します:

import { defineStore } from "pinia";

export const nameStore = defineStore('name', {
    state: () => {
        return {
            list: ['小紅', '小美', '胖丫']
        }
    }
})

次に、counter.tsにインポートし、import {jspangStore} from './jspang'を行い、action内で呼び出します:

 actions: {
    getList() {
      console.log(nameStore().list);
    }
  }

コンソールを確認すると、別のストアのstateを正常に呼び出すことができ、store間の相互呼び出しが成功しました。

VueDevtools をサポート#

Pinia は新人ですが、すでに VueDevtools を全面的にサポートしています。これは実際のプロジェクト開発におけるデバッグに大いに役立ちます。特に、VueDevtools を開くと、非常に可愛らしいパイナップルのロゴが見えます!image.png

開発中の気分も良くなりますね、ハハハ。

注意:Pinia v2 を使用している場合は、Vue Devtoolsを v6 バージョンにアップグレードしてください。

Pinia 実践:アバターを変更#

これまでの説明を踏まえ、実際のプロジェクトでpiniaを活用してみましょう。開発の背景:ウェブページを作成する際、登録機能が関与することが多く、ユーザーのアバターはログイン前ログイン後で異なります。アバターを変更するためにクリックイベントを 1 つだけ作成すると、ページをリフレッシュしたり移動したりすると元に戻ってしまい、状態が保存されません。この時、私たちの pinia を活用できます。

注意:pinia のデータを永続的に保存するため(localstorage または sessionstorage に保存するため)、プラグインをインストールする必要があります:pinia-plugin-persist。これにより、操作がより便利になります。詳細は公式文書を参照してください。

1. ストアを作成#

最初のステップはストアを作成することです(ここでは関連環境がすでに設定されていることを前提としています)。store/user.tsを作成し、具体的なコードは以下の通りです:

import { defineStore } from 'pinia';

export const mainStore = defineStore('main', {
    state: () => {
        return {
            login: require('../assets/images/login.png')
        }
    },
    // 永続化を有効にする
    persist: {
        enabled: true,
        strategies: [
            { storage: localStorage, paths: ['login'] }
        ],
    },
    getters: {

    },
    actions: {
       
    }
})

成功裏に作成した後、ユーザーアバターストアに保存しました。次は、コンポーネントでそれを使用します。

2. コンポーネントで呼び出す#

<!-- アバター -->
<a class="face" href="#/login">
   <img :src="store.login" alt="" />
</a>

ブラウザを開いて確認します:image.png

成功裏に呼び出しました!次は最も重要なステップです。ログイン後にアバターが正常にローカルに保存されるようにします。この時、直接actionsにデータを変更する操作を追加します:

actions: {
        changeHeadShot() {
            console.log('データが正常に保存されました');
            this.login = require('../assets/images/head.png')
        }
    }

作成したactionをコンポーネントで使用します:

<template>
  <!-- 不要なコードを省略 (ここではvantのコンポーネントを使用しています)-->
      <van-col span="8" @click="headerC">
        <van-button class="btn2" plain hairlin type="primary" to="/">
          <p class="text">ログイン</p>
        </van-button>
      </van-col>
</template>

<script setup>
//ストアをインポート
import { mainStore } from '@/store/user'
const login = mainStore()

//アバターを変更する関数を実装
function headerC() {
  login.changeHeadShot()
}
</script>

<style scoped>
/* 不要なコードを省略 */
</style>

次は「奇跡を目撃する」時です:ログインボタンをクリックすると、アバターが変更されます:image.png

この時、どんなにリフレッシュしても、アバターは変わりません。コンソールを開いてアプリケーションのストレージを確認すると、ログインアバターがローカルのブラウザに保存されていることがわかります:

image.png

結語#

要するに、あなたが以前に Vuex に触れたことがあるかどうかにかかわらず、私はPiniaの使用を強くお勧めします。Vuex に比べて、より良い互換性を持ち、Vuex の基盤の上にMutationを取り除き、文法をより簡潔にし、Vue3 のComposition apiにより適合しています。Vuex はもはや更新されず、現在はメンテナンス状態にありますが、Pinia は次世代の Vuex として、学び、使用しない理由は何もありません。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。