Pinia 試圖盡可能接近 Vuex 的理念。它旨在測(cè)試 Vuex 下一次迭代的提案,并且取得了成功,因?yàn)槲覀兡壳坝幸粋€(gè)針對(duì) Vuex 5 的開放 RFC,其 API 與Pinia 使用的 API 非常相似。Pinia 的作者 I (Eduardo) 是 Vue.js 核心團(tuán)隊(duì)的一員,并積極參與 Router 和 Vuex 等 API 的設(shè)計(jì)。我個(gè)人對(duì)這個(gè)項(xiàng)目的意圖是重新設(shè)計(jì)使用全局 Store 的體驗(yàn),同時(shí)保持 Vue 平易近人的哲學(xué)。我讓 Pania 的 API 與 Vuex 一樣接近,因?yàn)樗粩嘞蚯鞍l(fā)展,使人們可以輕松遷移到 Vuex,甚至在未來(lái)融合這兩個(gè)項(xiàng)目(在 Vuex 下)。
雖然 Vuex 通過(guò) RFC 從社區(qū)收集盡可能多的反饋,但 Pania 沒(méi)有。我根據(jù)我在開發(fā)應(yīng)用程序、閱讀其他人的代碼和在 Discord 上回答問(wèn)題的經(jīng)驗(yàn)來(lái)測(cè)試想法。這使我能夠提供一個(gè)有效的解決方案,經(jīng)常發(fā)布,并在人們使用它時(shí)通過(guò)在主要版本中進(jìn)行重大更改(在第一個(gè)穩(wěn)定版本后不太可能進(jìn)行重大更改)(如有必要)來(lái)改進(jìn)它。
與 Vuex 3.x/4.x 對(duì)比#
Vuex 3.x 是 Vue 2 的 Vuex 而 Vuex 4.x 是 Vue 3
Pinia API 與 Vuex ≤4 有很大不同,即:
突變不再存在。他們經(jīng)常被認(rèn)為非常冗長(zhǎng)。他們最初帶來(lái)了 devtools 集成,但這不再是問(wèn)題。
無(wú)需創(chuàng)建自定義的復(fù)雜包裝器來(lái)支持 TypeScript,所有內(nèi)容都是類型化的,并且 API 的設(shè)計(jì)方式盡可能地利用 TS 類型推斷。
不再需要注入、導(dǎo)入函數(shù)、調(diào)用它們,享受自動(dòng)補(bǔ)全!
無(wú)需動(dòng)態(tài)添加商店,默認(rèn)情況下它們都是動(dòng)態(tài)的,您甚至不會(huì)注意到。請(qǐng)注意,您仍然可以隨時(shí)手動(dòng)使用商店來(lái)注冊(cè)它,但因?yàn)樗亲詣?dòng)的,所以您無(wú)需擔(dān)心。
不再有模塊的嵌套結(jié)構(gòu)。您仍然可以通過(guò)在另一個(gè)商店中導(dǎo)入和使用商店來(lái)隱式嵌套商店,但 Pinia 通過(guò)設(shè)計(jì)提供扁平結(jié)構(gòu),同時(shí)仍然支持商店之間的交叉組合方式。
沒(méi)有命名空間模塊。鑒于商店的扁平架構(gòu),“命名空間”商店是其定義方式所固有的,您可以說(shuō)所有商店都是命名空間的。
安裝使用
yarn add pinia@next
npm install pinia@next
該版本與Vue 3兼容,如果你正在尋找與Vue 2.x兼容的版本,請(qǐng)查看v1分支
使用
mian.ts/mian.js引入
import { createPinia } from'pinia'
app.use(createPinia())

src文件夾下創(chuàng)建一個(gè)存放倉(cāng)庫(kù)的文件夾

文件中使用
在深入研究核心概念之前,我們需要知道 store 是使用定義的defineStore(),并且它需要一個(gè)唯一的名稱,作為第一個(gè)參數(shù)傳遞:
一旦實(shí)例化,你可以訪問(wèn)定義的任何財(cái)產(chǎn)state,getters以及actions直接在店里

這個(gè)名稱,也稱為id,是必要的,Pinia 使用它來(lái)將商店連接到開發(fā)工具。將返回的函數(shù)命名為use...是一種跨可組合的約定,以使其使用慣用語(yǔ)。
state
創(chuàng)建state

使用state
直接引入定義好的文件,然后執(zhí)行拋出的方法
pinia完全支持typescript,無(wú)需創(chuàng)建自定義的復(fù)雜包裝器來(lái)支持 TypeScript,所有內(nèi)容都是類型化的,并且 API 的設(shè)計(jì)方式盡可能地利用 TS 類型推斷。


注意store是一個(gè)用包裹的對(duì)象reactive,這意味著不需要.value在 getter 之后寫入,但是,就像props在 中一樣setup,我們無(wú)法對(duì)其進(jìn)行解構(gòu)
storeToRefs() 解構(gòu)state
為了在保持其反應(yīng)性的同時(shí)從存儲(chǔ)中提取屬性,您需要使用storeToRefs(). 它將為任何反應(yīng)性屬性創(chuàng)建引用。當(dāng)您僅使用 store 中的狀態(tài)但不調(diào)用任何操作時(shí)


直接讀寫
默認(rèn)情況下,您可以通過(guò)store實(shí)例訪問(wèn)狀態(tài)直接讀寫狀態(tài),但不會(huì)影響倉(cāng)庫(kù)原有值

不會(huì)影響倉(cāng)庫(kù)中原來(lái)的值

$reset()重置狀態(tài)
可以通過(guò)調(diào)用store 上的方法將狀態(tài)重置為其初始值$reset():
需要搭配action來(lái)操作state中的值發(fā)生變化,在此只展示用法


state響應(yīng)式
在組件中使用到state時(shí),盡量使用computed包裹,因?yàn)閟etup只會(huì)執(zhí)行一次,如果直接 const counter = store.counter的話,只會(huì)拿到第一次初始化的值,如果數(shù)據(jù)發(fā)生變化不會(huì)更新
使用computed的話,一旦數(shù)據(jù)發(fā)生改變數(shù)據(jù)就會(huì)改變,而且computed自帶數(shù)據(jù)緩存

直接改變狀態(tài)
這里直接引入官網(wǎng)的說(shuō)明,因?yàn)楸救擞X(jué)得直接操作state中的數(shù)據(jù)難以維護(hù)

更換state
可以通過(guò)將商店的$state屬性設(shè)置為新對(duì)象來(lái)替換商店的整個(gè)狀態(tài)
store.$state = { counter: 666, name: 'Paimon' }
getters
Getter 完全等同于 Store 狀態(tài)的計(jì)算值。它們可以用 中的getters屬性定義defineStore()。他們收到state作為第一個(gè)參數(shù)來(lái)鼓勵(lì)使用箭頭函數(shù)

getter使用this
大多數(shù)情況下,getter 只會(huì)依賴狀態(tài),但是,他們可能需要使用其他 getter。
正因?yàn)槿绱耍覀兛梢酝ㄟ^(guò)定義一個(gè)常規(guī)函數(shù)來(lái)訪問(wèn)整個(gè) store 實(shí)例,但是需要定義返回類型的類型(在 TypeScript 中)。
這是由于 TypeScript 中的一個(gè)已知限制,并且不會(huì)影響使用箭頭函數(shù)定義的 getter 或不使用的 getter:

直接使用this需要定義返回類型,如果不定義返回類型會(huì)報(bào)錯(cuò)

訪問(wèn)gettes
可以直接在 store 實(shí)例上訪問(wèn) getter


可以使用computed包裹

訪問(wèn)其他 getter
與計(jì)算屬性一樣,您可以組合多個(gè) getter。通過(guò) 訪問(wèn)任何其他 getter this。即使您不使用 TypeScript,您也可以使用JSDoc提示您的 IDE 類型:
定義一個(gè)user倉(cāng)庫(kù)文件

index文件中引入user倉(cāng)庫(kù)
使用


actions
這里與 Vuex 有極大的不同,Pinia 僅提供了一種方法來(lái)定義如何更改狀態(tài)的規(guī)則,放棄 mutations 只依靠 Actions,這是一項(xiàng)重大的改變。
Pinia 讓 Actions 更加的靈活
可以通過(guò)組件或其他 action 調(diào)用
可以從其他 store 的 action 中調(diào)用
直接在商店實(shí)例上調(diào)用
支持同步或異步
有任意數(shù)量的參數(shù)
可以包含有關(guān)如何更改狀態(tài)的邏輯(也就是 vuex 的 mutations 的作用)
可以 $patch 方法直接更改狀態(tài)屬性


使用
