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を正常に呼び出せたことがわかります。ストア間の相互呼び出しが成功しました。

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 として、学び使用しない理由は何でしょうか?

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