在 Vue 裡面使用 pinia 管理狀態

pinia 是 Vue 官方推薦的狀態管理工具,可以解決跨元件之間資料傳遞要反覆的 props 及 emit 的問題,只要把資料跟方法放在 store 裡面,就可以讓所有的元件取用,不但傳遞變簡單了,在管理資料上面也變得更清楚。

首先安裝 pinia

npm install pinia

main.js 中初始化

import { createApp } from "vue";
import App from "./App.vue";
import { createPinia } from "pinia";

const pinia = createPinia();
const app = createApp(App);

app.use(pinia);

app.mount("#app");

在 src 下面建立 stores 資料夾,然後在 stores 裡面建立 user.js。

import { defineStore } from "pinia";

// userStore 為自定義名稱
// {屬性參數}
export default defineStore("userStore", {
  // data
  state: () => ({ name: "鋼鐵人", friend: "蜘蛛人" }),
  // computed
  getters: {
    getUserName(state) {
      return `${state.name}${state.friend}是好朋友`;
    }
  },
  // methods
  actions: {
    // 可以使用 this,所以不用箭頭函式
    updateFriend() {
      this.friend = "美國隊長";
    }
  }
});

HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>{{ name }},{{ friend }}</h2>
    <h2>{{ getUserName }}</h2>
    <button type="button" @click="updateFriend">更新復仇者好友</button>
  </div>
</template>

<script>
import { mapState, mapActions } from "pinia";
import userStore from "@/stores/user";
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  computed: {
    ...mapState(userStore, ["name", "friend", "getUserName"]),
  },
  methods: {
    ...mapActions(userStore, ["updateFriend"]),
  },
};
</script>

在 Composition 中使用 pinia

簡單初始化,首先

import userStore from "@/stores/user";

使用 reactive 格式

然後在 setup()userStore 賦值給一個常數 user,記得要 把 userreturn 出去。

然後在 HTML 中使用 {{ user.變數名稱或方法 }} , 就可以綁定 user.js 裡面 state 定義的資料、 gettersactions 中的方法,而且這樣的情形下,資料及方法都是 reactive 格式的,所以可以做到雙向綁定。

HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>{{ user.name }},{{ user.friend }}</h2>
    <h2>{{ user.getFriendName }}</h2>
    <button type="button" @click="user.updateFriend">更新復仇者好友</button>
  </div>
</template>

<script>
import userStore from "@/stores/user";
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  setup() {
    const user = userStore();
		//state 中的資料為 reactive 格式
    return {
      user,
    };
  },
};
</script>

使用 ref 格式

要使用 ref 格式,除了 import userStore from "@/stores/user";之外,還必須匯入一個 pinia 提供的 { storeToRefs } 方法,把 store 中定義的方法跟資料轉為 ref 格式:

import { storeToRefs } from "pinia";

然後在 setup() 中,取出 store 中的變數及方法:

const { name, friend, getFriendName } = storeToRefs(user);
// 如果要改變 變數的值,記得加上 .value

name.value = '雷神'

return 的時候除了 user 之外, namefriendgetFriendName 也要記得 return 出去。

這時 HTML 中的 {{ user.xxxx }} 就可以拿掉了。但是如果要在 setup() 中更改 變數的值,就要像使用 ref 一樣,加上 xxxx.value

如果在 state 中不用作到雙向綁定的,就直接取出

// 不用雙向綁定 直接取出
const  { updateFriend } = user;

HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>{{ user.name }},{{ user.friend }}</h2>
    <h2>{{ user.getFriendName }}</h2>
    <!-- user 可以拿掉 -->
    <h2>{{ name }},{{ friend }}</h2>
    <h2>{{ getFriendName }}</h2>
    <!-- 雙向綁定也可以 -->
    <input type="text" v-model="user.name" />
    <button type="button" @click="user.updateFriend">更新復仇者好友</button>
  </div>
</template>

<script>
import { storeToRefs } from "pinia";
import userStore from "@/stores/user";
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  setup() {
    const user = userStore();
    // 轉成 ref 格式
    const { name, friend, getFriendName } = storeToRefs(user);
    // ref 格式,state 中的變數須加上 .value
    name.value = "雷神";
		// 不用雙向綁定 直接取出
    const  { updateFriend } = user;
    return {
      user,
      name,
      friend,
      getFriendName,
    };
  },
};
</script>

使用 pinia 提供的 patch 方法修改資料:

function updateData() {
      user.$patch({
        name: "浩克",
        friend: "薩諾斯",
      });
    }

使用 pinia 提供的 reset 方法重置資料:

function reset() {
      user.$reset();
}

在 Vue 裡面使用 pinia 管理狀態
https://popeye-ux.github.io/2023/02/06/piniabeginner/
作者
POPEYE
發布於
2023年2月6日
許可協議