Pinia 定義 Store

2023-09-28 11:36 更新

定義 Store

在深入研究核心概念之前,我們得知道 Store 是用 defineStore() 定義的,它的第一個參數(shù)要求是一個獨一無二的名字:

  1. import { defineStore } from 'pinia'
  2. // 你可以對 `defineStore()` 的返回值進行任意命名,但最好使用 store 的名字,同時以 `use` 開頭且以 `Store` 結(jié)尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
  3. // 第一個參數(shù)是你的應用中 Store 的唯一 ID。
  4. export const useAlertsStore = defineStore('alerts', {
  5. // 其他配置...
  6. })

這個名字 ,也被用作 id ,是必須傳入的, Pinia 將用它來連接 store 和 devtools。為了養(yǎng)成習慣性的用法,將返回的函數(shù)命名為 use... 是一個符合組合式函數(shù)風格的約定。

defineStore() 的第二個參數(shù)可接受兩類值:Setup 函數(shù)或 Option 對象。

Option Store

與 Vue 的選項式 API 類似,我們也可以傳入一個帶有 state、actionsgetters 屬性的 Option 對象

```js {2-10} export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), getters: { double: (state) => state.count * 2, }, actions: { increment() { this.count++ }, }, })

  1. 你可以認為 `state` store 的數(shù)據(jù) (`data`),`getters` store 的計算屬性 (`computed`),而 `actions` 則是方法 (`methods`)。
  2. 為方便上手使用,Option Store 應盡可能直觀簡單。
  3. ## Setup Store
  4. 也存在另一種定義 store 的可用語法。與 Vue 組合式 API [setup 函數(shù)](https://cn.vuejs.org/api/composition-api-setup.html) 相似,我們可以傳入一個函數(shù),該函數(shù)定義了一些響應式屬性和方法,并且返回一個帶有我們想暴露出去的屬性和方法的對象。
  5. ```js
  6. export const useCounterStore = defineStore('counter', () => {
  7. const count = ref(0)
  8. function increment() {
  9. count.value++
  10. }
  11. return { count, increment }
  12. })

Setup Store 中:

  • ref() 就是 state 屬性
  • computed() 就是 getters
  • function() 就是 actions

Setup store 比 Option Store 帶來了更多的靈活性,因為你可以在一個 store 內(nèi)創(chuàng)建偵聽器,并自由地使用任何組合式函數(shù)。不過,請記住,使用組合式函數(shù)會讓 SSR 變得更加復雜。

你應該選用哪種語法?

在 Vue 中如何選擇組合式 API 與選項式 API 一樣,選擇你覺得最舒服的那一個就好。如果你還不確定,可以先試試 Option Store

使用 Store

雖然我們前面定義了一個 store,但在我們使用 <script setup> 調(diào)用 useStore()(或者使用 setup() 函數(shù),像所有的組件那樣) 之前,store 實例是不會被創(chuàng)建的:

  1. <script setup>
  2. import { useCounterStore } from '@/stores/counter'
  3. // 可以在組件中的任意位置訪問 `store` 變量 ?
  4. const store = useCounterStore()
  5. </script>

你可以定義任意多的 store,但為了讓使用 pinia 的益處最大化(比如允許構(gòu)建工具自動進行代碼分割以及 TypeScript 推斷),你應該在不同的文件中去定義 store。

如果你還不會使用 setup 組件,你也可以通過映射輔助函數(shù)來使用 Pinia。

一旦 store 被實例化,你可以直接訪問在 store 的 state、gettersactions 中定義的任何屬性。我們將在后續(xù)章節(jié)繼續(xù)了解這些細節(jié),目前自動補全將幫助你使用相關屬性。

請注意,store 是一個用 reactive 包裝的對象,這意味著不需要在 getters 后面寫 .value,就像 setup 中的 props 一樣,如果你寫了,我們也不能解構(gòu)它

  1. <script setup>
  2. const store = useCounterStore()
  3. // ? 這將不起作用,因為它破壞了響應性
  4. // 這就和直接解構(gòu) `props` 一樣
  5. const { name, doubleCount } = store // [!code warning]
  6. name // 將始終是 "Eduardo" // [!code warning]
  7. doubleCount // 將始終是 0 // [!code warning]
  8. setTimeout(() => {
  9. store.increment()
  10. }, 1000)
  11. // ? 這樣寫是響應式的
  12. // ???? 當然你也可以直接使用 `store.doubleCount`
  13. const doubleValue = computed(() => store.doubleCount)
  14. </script>

為了從 store 中提取屬性時保持其響應性,你需要使用 storeToRefs()。它將為每一個響應式屬性創(chuàng)建引用。當你只使用 store 的狀態(tài)而不調(diào)用任何 action 時,它會非常有用。請注意,你可以直接從 store 中解構(gòu) action,因為它們也被綁定到 store 上:

  1. <script setup>
  2. import { storeToRefs } from 'pinia'
  3. const store = useCounterStore()
  4. // `name``doubleCount` 是響應式的 ref
  5. // 同時通過插件添加的屬性也會被提取為 ref
  6. // 并且會跳過所有的 action 或非響應式 (不是 ref 或 reactive) 的屬性
  7. const { name, doubleCount } = storeToRefs(store)
  8. // 作為 action 的 increment 可以直接解構(gòu)
  9. const { increment } = store
  10. </script>
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號