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
留言分享你的想法!
avatar-img
Jeremy Ho的沙龍
19會員
37內容數
這個專題用來存放我在學習網頁開發時的心得及知識。
Jeremy Ho的沙龍的其他內容
2023/11/22
用 vue3-openlayers 畫張地圖吧
Thumbnail
2023/11/22
用 vue3-openlayers 畫張地圖吧
Thumbnail
2023/11/13
Vue3 筆記,指令進階篇
Thumbnail
2023/11/13
Vue3 筆記,指令進階篇
Thumbnail
2023/11/12
Vue3 學習筆記,vue-router 篇。
Thumbnail
2023/11/12
Vue3 學習筆記,vue-router 篇。
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
在這篇文章中,我們將討論如何在 Vue 應用中使用路由、GitHub Pages 部署以及狀態管理工具 Pinia。這些概念在開發上通常會使用到,讓我們一步一步深入這些重要的概念!
Thumbnail
在這篇文章中,我們將討論如何在 Vue 應用中使用路由、GitHub Pages 部署以及狀態管理工具 Pinia。這些概念在開發上通常會使用到,讓我們一步一步深入這些重要的概念!
Thumbnail
Vue 筆記,Nuxt 簡介
Thumbnail
Vue 筆記,Nuxt 簡介
Thumbnail
Vue3 筆記,指令進階篇
Thumbnail
Vue3 筆記,指令進階篇
Thumbnail
Vue3 學習筆記,vue-router 篇。
Thumbnail
Vue3 學習筆記,vue-router 篇。
Thumbnail
Vue3 學習筆記,用 Pinia 管理資料與邏輯
Thumbnail
Vue3 學習筆記,用 Pinia 管理資料與邏輯
Thumbnail
Vue3 學習筆記,元件與資料傳遞篇
Thumbnail
Vue3 學習筆記,元件與資料傳遞篇
Thumbnail
Vue3 學習筆記,專案建立與基礎響應式篇
Thumbnail
Vue3 學習筆記,專案建立與基礎響應式篇
Thumbnail
專案建好了,那先來講 Vue 的專案架構 詳細內容很多,所以我挑重點講 public index.html public/index.html 是 Vue 頁面的 entry point,進入一個 Vue 頁面會先進 public/index.html,再套用 App.vue,最後才是進入你寫的 .
Thumbnail
專案建好了,那先來講 Vue 的專案架構 詳細內容很多,所以我挑重點講 public index.html public/index.html 是 Vue 頁面的 entry point,進入一個 Vue 頁面會先進 public/index.html,再套用 App.vue,最後才是進入你寫的 .
Thumbnail
S1.建立資料庫 user S2.建立 index.htm a.載入 vue.js、jquery、bootstrap b.版面建立 S3.vue.js程式 新增、查看列表、互動視窗、修改、刪除 index.htm VueControl.js 原碼:https://reurl.cc/e3k8yL
Thumbnail
S1.建立資料庫 user S2.建立 index.htm a.載入 vue.js、jquery、bootstrap b.版面建立 S3.vue.js程式 新增、查看列表、互動視窗、修改、刪除 index.htm VueControl.js 原碼:https://reurl.cc/e3k8yL
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News