Vue3 筆記 | Pinia 管理全域資料

更新於 發佈於 閱讀時間約 9 分鐘

Vue 的狀態 (資料) 是靠著 ref reactive 儲存,然後靠著 propsemit 在組件中傳遞,可是如果今天專案一大,難免會有需要資料共享的狀況,那時不免要 propsprops 去、emitemit 去。

針對這個問題,當然也可以選擇使用 Provide-Inject 的方式來傳遞,但其實有更好的做法,就是用 Pinia 統一管理資料。



Pinia 使用

在 Vue 專案建立的時候其實就有選項問說要不要使用 Pinia 來做管理,如果選了的話,當專案建立完會在 /src 下發現一個 stores 資料夾,同時在 main.js 中也會發現 Pinia 自動被引入:

import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)

app.use(createPinia())

app.mount('#app')


如果是舊專案要引入 Pinia,也可以透過 npm install pinia 的方式下載安裝,在自己手動修改 main.js 的內容。



認識 store

新專案會在 /src/stores 下預設建立好一個 counter.js 作為範例,它就是一個 store。

Store 負責儲存可供全域使用的狀態及邏輯,換句話說,它可以儲存 data、computed 以及 method。

定義一個 store,必須先從 pinia 引入 defineStore,命名的時候通常以 "use 開頭 + 這個 store 主要幹的事 + store 結尾"defineStore 接受兩個參數,一個是 store id,大可直接放入去掉 use 的命名;第二個是一個 arrow function,裡面就是儲存資料或邏輯的地方。

現在來看一下 pinia 預先在專案裡給我們的例子:

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}

return { count, doubleCount, increment }
})

會發現 store 裡的資料或邏輯寫法跟在 <script setup> 裡寫的基本一樣,這是組合式的寫法,較早一點的選項式寫法更簡便易懂。然後透過 return 把資料或邏輯給拋出來給全域使用。



引用 store 內部資料或邏輯

在組件中我們可以直接 import 要用的 store,並把內容除存在某變數之中 (xxStore 之類的),之後可以在組件中調用 xxStore 內部的資料或邏輯。

App.vue:

<script setup>
import {useCounterStore} from '@/stores/counter'

const store = useCounterStore()
</script>

<template>
<h1>{{ store.count }}</h1>
<button @click="store.increment">Add</button>
</template>

我們可以看到畫面渲染出 store 中定義的 count 並且按鈕也可以運作。



Store 的解構

Store 的解構一句你想解構的是資料還是方法有不同做法。如果單純是方法可以直接解構,但如果是響應式資料 (包括 computed) 則要使用 storeToRefs 來做提取,看一下官方的例子,來實做看看:

App.vue:

<script setup>
import { storeToRefs } from 'pinia'
import {useCounterStore} from '@/stores/counter'

const store = useCounterStore()
const {count, doubleCount} = storeToRefs(store)
const {increment} = store

</script>

<template>
<h1>{{ count }}</h1>
<button @click="increment">Add</button>
</template>

畫面一樣可以運作,解構成功!



Store 狀態的重置

我們可以在 store 中定義 $reset 方法來讓狀態重置:

Counter.js:

// 添加 reset 方法
const $reset = () => count.value = 0

return { count, doubleCount, increment, $reset }

App.vue:

<script setup>
import {useCounterStore} from '@/stores/counter'

const store = useCounterStore()
</script>

<template>
<h1>{{ store.count }}</h1>
<button @click="store.increment">Add</button>
<button @click="store.$reset">Reset to 0</button>
</template>

當我們點擊重置按鈕時,畫面數字就會歸零了。



數據修改

存在 store 中的數據有三種修改方式:

  1. 直接修改,但不推薦:
<button @click="store.count++">Add</button>
  1. 引用方法:
<button @click="store.increment">Add</button>
  1. 使用 $patch
const addCount = () =>{
store.$patch(state =>{
state.count++
})
}

<button @click="addCount">Add</button>



數據監聽

可不可以用 watch?當然可以,但 pinia 提供了屬於它的 $subscribe 用法。

Subscribe 接收兩個參數,一個是 mutation,一個是監聽對象。Mutation console.log 出來又有三個數性值:

  1. type:記錄數據變化是通過什麼途徑。
  2. storeId:就當前 store 的 id。
  3. events:state 改變的具體數據。

我們在 App.vue 中新增一個 subscribe

store.$subscribe((mutation, state) =>{
console.log('Something changed!')
})

當我們點擊按鈕後會 console.logSomething changed!

raw-image

我們也可以用 watch 做監聽,但記得添加深層監聽:

watch(store, state =>{
console.log(`watch here`, state)
}, {deep : true})



Action (方法) 的監聽

如同監聽數據一般,Vue 可以用 $onAction 監聽方法的使用,比方說我要監聽 increment 這個函式的執行時間:

store.$onAction(({ name, after }) => {
if (name === 'increment') {
const startTime = Date.now();

after(() => {
console.log(
`Finished "${name}" after ${
Date.now() - startTime
}ms.`
);
});
}
})

打開 devtool 就可以看到監測到的執行時間。

raw-image



參考資料

  1. Pinia 官方文件
  2. Vue3 + Vite 快速上手 Get Startrd EP6 - Pinia 的全域資料管理!
avatar-img
18會員
37內容數
這個專題用來存放我在學習網頁開發時的心得及知識。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Jeremy Ho的沙龍 的其他內容
Vue3 學習筆記,元件與資料傳遞篇
Vue3 學習筆記,專案建立與基礎響應式篇
AWS 佈署簡單操作以及 RDS 建立篇
AWS 部署學習 - Day1,註冊與安裝 EB
記錄一下 API 串接的四種方式 www
Vue3 學習筆記,元件與資料傳遞篇
Vue3 學習筆記,專案建立與基礎響應式篇
AWS 佈署簡單操作以及 RDS 建立篇
AWS 部署學習 - Day1,註冊與安裝 EB
記錄一下 API 串接的四種方式 www
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
在這篇文章中,我們將討論如何在 Vue 應用中使用路由、GitHub Pages 部署以及狀態管理工具 Pinia。這些概念在開發上通常會使用到,讓我們一步一步深入這些重要的概念!
Thumbnail
狀態管理在 Vue 應用中非常重要,尤其是當多個組件需要共享狀態時。每個 Vue 組件管理自己的響應式狀態,但隨著組件數量增加,簡單的管理方式可能變得複雜。這時,可以使用如 Pinia 的狀態管理庫來簡化這一過程。Pinia 提供了一個更簡單的 API 和更強的類型推斷,並由 Vue 核心團隊維護。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。 層級展示圖
一般而言,組件之間的資料傳遞,可以使用 props 來達成,不過一旦層級過多的時候,props 就要逐層向下傳遞,會越來越麻煩且複雜。 而 provide、inject 可以解決這個問題,它可以提供一個「源頭」,子組件們可以藉由同一個源頭取得對應的資料,且沒有層級分別,都可以取得,就不用逐層傳遞資
Thumbnail
在 Vue 中,組件是構建應用程式的基本單位,而 props 是組件間傳遞資料的主要方式之一,本文將介紹 Vue 中的 props,並通過實際範例展示如何使用 props 實現組件間的資料傳遞。
Thumbnail
v-model 指令是 Vue 中一個非常重要的功能,它實現了表單輸入和應用狀態之間的雙向綁定。本文將介紹如何使用 v-model 指令。
Thumbnail
在Vue中,v-for指令是用於渲染列表數據。本文將介紹v-for指令的用法,並提供簡單的範例來幫助你理解如何在你的 Vue 應用中有效地使用v-for指令。
Thumbnail
Vue 是尤雨溪所開發的一個前端框架,Vue 提供了響應式數據綁定和組件化的開發模式,能方便開發者構建出具有良好交互性的前端應用。而 Vite 則是一個前端構建工具,用途是提供更快的開發體驗。然後,本文將介紹如何使用 Vite 建立一個 Vue 專案的開發環境,這是你學習 Vue 的第一步。
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
在這篇文章中,我們將討論如何在 Vue 應用中使用路由、GitHub Pages 部署以及狀態管理工具 Pinia。這些概念在開發上通常會使用到,讓我們一步一步深入這些重要的概念!
Thumbnail
狀態管理在 Vue 應用中非常重要,尤其是當多個組件需要共享狀態時。每個 Vue 組件管理自己的響應式狀態,但隨著組件數量增加,簡單的管理方式可能變得複雜。這時,可以使用如 Pinia 的狀態管理庫來簡化這一過程。Pinia 提供了一個更簡單的 API 和更強的類型推斷,並由 Vue 核心團隊維護。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
VUE為單向資料流的框架,在鄰近層級之間我們可以依靠 props 由父層向子層來傳遞需要的資料,然而遇到跨層級的架構時,雖然也是可以一層層傳進去,只是這會造成多餘的處理及凌亂的程式碼,因此才有了 "provide" 來解決我們跨層級的需求。 層級展示圖
一般而言,組件之間的資料傳遞,可以使用 props 來達成,不過一旦層級過多的時候,props 就要逐層向下傳遞,會越來越麻煩且複雜。 而 provide、inject 可以解決這個問題,它可以提供一個「源頭」,子組件們可以藉由同一個源頭取得對應的資料,且沒有層級分別,都可以取得,就不用逐層傳遞資
Thumbnail
在 Vue 中,組件是構建應用程式的基本單位,而 props 是組件間傳遞資料的主要方式之一,本文將介紹 Vue 中的 props,並通過實際範例展示如何使用 props 實現組件間的資料傳遞。
Thumbnail
v-model 指令是 Vue 中一個非常重要的功能,它實現了表單輸入和應用狀態之間的雙向綁定。本文將介紹如何使用 v-model 指令。
Thumbnail
在Vue中,v-for指令是用於渲染列表數據。本文將介紹v-for指令的用法,並提供簡單的範例來幫助你理解如何在你的 Vue 應用中有效地使用v-for指令。
Thumbnail
Vue 是尤雨溪所開發的一個前端框架,Vue 提供了響應式數據綁定和組件化的開發模式,能方便開發者構建出具有良好交互性的前端應用。而 Vite 則是一個前端構建工具,用途是提供更快的開發體驗。然後,本文將介紹如何使用 Vite 建立一個 Vue 專案的開發環境,這是你學習 Vue 的第一步。