Vue 新的狀態(tài)管理 Pinia

Pinia 和 Vuex

Vuex:State、Gettes、Mutations(同步)畴蹭、Actions(異步)

Pinia:State菱涤、Gettes、Actions(同步異步都支持)

Vuex 當(dāng)前最新版是 4.x

Vuex4 用于 Vue3

Vuex3 用于 Vue2

Pinia 當(dāng)前最新版是 2.x

即支持 Vue2 也支持 Vue3

就目前而言 Pinia 比 Vuex 好太多了佑女,解決了 Vuex 的很多問(wèn)題,所以筆者也非常建議直接使用 Pinia,尤其是 TypeScript 的項(xiàng)目

Pinia 核心特性

  • Pinia 沒(méi)有 Mutations

  • Actions 支持同步和異步

  • 沒(méi)有模塊的嵌套結(jié)構(gòu)

  • Pinia 通過(guò)設(shè)計(jì)提供扁平結(jié)構(gòu)康辑,就是說(shuō)每個(gè) store 都是互相獨(dú)立的,誰(shuí)也不屬于誰(shuí)轿亮,也就是扁平化了疮薇,更好的代碼分割且沒(méi)有命名空間。當(dāng)然你也可以通過(guò)在一個(gè)模塊中導(dǎo)入另一個(gè)模塊來(lái)隱式嵌套 store我注,甚至可以擁有 store 的循環(huán)依賴關(guān)系

  • 更好的 TypeScript 支持

  • 不需要再創(chuàng)建自定義的復(fù)雜包裝器來(lái)支持 TypeScript 所有內(nèi)容都類型化按咒,并且 API 的設(shè)計(jì)方式也盡可能的使用 TS 類型推斷

  • 不需要注入、導(dǎo)入函數(shù)但骨、調(diào)用它們励七,享受自動(dòng)補(bǔ)全智袭,讓我們開(kāi)發(fā)更加方便

  • 無(wú)需手動(dòng)添加 store,它的模塊默認(rèn)情況下創(chuàng)建就自動(dòng)注冊(cè)的

  • Vue2 和 Vue3 都支持

  • 除了初始化安裝和SSR配置之外掠抬,兩者使用上的API都是相同的

  • 支持 Vue DevTools

  • 跟蹤 actions, mutations 的時(shí)間線

  • 在使用了模塊的組件中就可以觀察到模塊本身

  • 支持 time-travel 更容易調(diào)試

  • 在 Vue2 中 Pinia 會(huì)使用 Vuex 的所有接口吼野,所以它倆不能一起使用

  • 但是針對(duì) Vue3 的調(diào)試工具支持還不夠完美,比如還沒(méi)有 time-travel 功能

  • 模塊熱更新

  • 無(wú)需重新加載頁(yè)面就可以修改模塊

  • 熱更新的時(shí)候會(huì)保持任何現(xiàn)有狀態(tài)

  • 支持使用插件擴(kuò)展 Pinia 功能

  • 支持服務(wù)端渲染

Pinia 使用

以 Vue3 + TypeScript 為例
安裝

npm install pinia

main.ts 初始化配置

import { createPinia } from 'pinia'
createApp(App).use(createPinia()).mount('#app')

在 store 目錄下創(chuàng)建一個(gè) user.ts 為例两波,我們先定義并導(dǎo)出一個(gè)名為 user 的模塊

import { defineStore } from 'pinia'
export const userStore = defineStore('user', {
   state: () => {
       return {
           count: 1,
           arr: []
      }
  },
   getters: { ... },
   actions: { ... }
})

defineStore 接收兩個(gè)參數(shù)
第一個(gè)參數(shù)就是模塊的名稱瞳步,必須是唯一的,多個(gè)模塊不能重名雨女,Pinia 會(huì)把所有的模塊都掛載到根容器上 第二個(gè)參數(shù)是一個(gè)對(duì)象谚攒,里面的選項(xiàng)和 Vuex 差不多

  • 其中 state 用來(lái)存儲(chǔ)全局狀態(tài),它必須是箭頭函數(shù)氛堕,為了在服務(wù)端渲染的時(shí)候避免交叉請(qǐng)求導(dǎo)致的數(shù)據(jù)狀態(tài)污染所以只能是函數(shù)馏臭,而必須用箭頭函數(shù)則為了更好的 TS 類型推導(dǎo)
  • getters 就是用來(lái)封裝計(jì)算屬性,它有緩存的功能
  • actions 就是用來(lái)封裝業(yè)務(wù)邏輯讼稚,修改 state

訪問(wèn) state

比如我們要在頁(yè)面中訪問(wèn) state 里的屬性 count
由于 defineStore 會(huì)返回一個(gè)函數(shù)括儒,所以要先調(diào)用拿到數(shù)據(jù)對(duì)象,然后就可以在模板中直接使用了

<template>
   <div>{{ user_store.count }}</div>
</template>
<script lang="ts" setup>
import { userStore } from '../store'
const user_store = userStore()
// 解構(gòu)
// const { count } = userStore()
</script>

比如像注釋中的解構(gòu)出來(lái)使用锐想,是完全沒(méi)有問(wèn)題的帮寻,只是注意了,這樣拿到的數(shù)據(jù)不是響應(yīng)式的赠摇,如果要解構(gòu)還保持響應(yīng)式就要用到一個(gè)方法 storeToRefs()固逗,示例如下

<template>
   <div>{{ count }}</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { userStore } from '../store'
const { count } = storeToRefs(userStore)
</script>

原因就是 Pinia 其實(shí)是把 state 數(shù)據(jù)都做了 reactive 處理,和 Vue3 的 reactive 同理藕帜,解構(gòu)出來(lái)的也不是響應(yīng)式烫罩,所以需要再做 ref 響應(yīng)式代理

getters

這個(gè)和 Vuex 的 getters 一樣,也有緩存功能洽故。如下在頁(yè)面中多次使用贝攒,第一次會(huì)調(diào)用 getters,數(shù)據(jù)沒(méi)有改變的情況下之后會(huì)讀取緩存

<template>
   <div>{{ myCount }}</div>
   <div>{{ myCount }}</div>
   <div>{{ myCount }}</div>
</template>

注意兩種方法的區(qū)別时甚,寫(xiě)在注釋里了

getters: {
   // 方法一隘弊,接收一個(gè)可選參數(shù) state
   myCount(state){
       console.log('調(diào)用了') // 頁(yè)面中使用了三次,這里只會(huì)執(zhí)行一次荒适,然后緩存起來(lái)了
       return state.count + 1
  },
   // 方法二梨熙,不傳參數(shù),使用 this
   // 但是必須指定函數(shù)返回值的類型刀诬,否則類型推導(dǎo)不出來(lái)
   myCount(): number{
       return this.count + 1
  }
}

更新和 actions

更新 state 里的數(shù)據(jù)有四種方法串结,我們先看三種簡(jiǎn)單的更新,說(shuō)明都寫(xiě)在注釋里了

<template>
   <div>{{ user_store.count }}</div>
   <button @click="handleClick">按鈕</button>
</template>
<script lang="ts" setup>
import { userStore } from '../store'
const user_store = userStore()
const handleClick = () => {
   // 方法一
   user_store.count++
   
   // 方法二,需要修改多個(gè)數(shù)據(jù)肌割,建議用 $patch 批量更新,傳入一個(gè)對(duì)象
   user_store.$patch({
       count: user_store.count1++,
       // arr: user_store.arr.push(1) // 錯(cuò)誤
       arr: [ ...user_store.arr, 1 ] // 可以帐要,但是還得把整個(gè)數(shù)組都拿出來(lái)解構(gòu)把敞,就沒(méi)必要
  })
   
   // 使用 $patch 性能更優(yōu),因?yàn)槎鄠€(gè)數(shù)據(jù)更新只會(huì)更新一次視圖
   
   // 方法三榨惠,還是$patch奋早,傳入函數(shù),第一個(gè)參數(shù)就是 state
   user_store.$patch( state => {
       state.count++
       state.arr.push(1)
  })
}
</script>

第四種方法就是當(dāng)邏輯比較多或者請(qǐng)求的時(shí)候赠橙,我們就可以封裝到示例中 store/user.ts 里的 actions 里

可以傳參數(shù)耽装,也可以通過(guò) this.xx 可以直接獲取到 state 里的數(shù)據(jù),需要注意的是不能用箭頭函數(shù)定義 actions期揪,不然就會(huì)綁定外部的 this 了

actions: {
   changeState(num: number){ // 不能用箭頭函數(shù)
       this.count += num
  }
}

調(diào)用

const handleClick = () => {
   user_store.changeState(1)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掉奄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凤薛,更是在濱河造成了極大的恐慌姓建,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缤苫,死亡現(xiàn)場(chǎng)離奇詭異速兔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)活玲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門涣狗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人舒憾,你說(shuō)我怎么就攤上這事镀钓。” “怎么了珍剑?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵掸宛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我招拙,道長(zhǎng)唧瘾,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任别凤,我火速辦了婚禮饰序,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘规哪。我一直安慰自己求豫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蝠嘉,像睡著了一般最疆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蚤告,一...
    開(kāi)封第一講書(shū)人閱讀 51,590評(píng)論 1 305
  • 那天努酸,我揣著相機(jī)與錄音,去河邊找鬼杜恰。 笑死获诈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的心褐。 我是一名探鬼主播舔涎,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼逗爹!你這毒婦竟也來(lái)了亡嫌?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤桶至,失蹤者是張志新(化名)和其女友劉穎昼伴,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體镣屹,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡圃郊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了女蜈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片持舆。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖伪窖,靈堂內(nèi)的尸體忽然破棺而出逸寓,到底是詐尸還是另有隱情,我是刑警寧澤覆山,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布竹伸,位于F島的核電站,受9級(jí)特大地震影響簇宽,放射性物質(zhì)發(fā)生泄漏勋篓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一魏割、第九天 我趴在偏房一處隱蔽的房頂上張望譬嚣。 院中可真熱鬧,春花似錦钞它、人聲如沸拜银。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尼桶。三九已至操灿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間泵督,已是汗流浹背牲尺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留幌蚊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓溃卡,卻偏偏與公主長(zhǎng)得像溢豆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瘸羡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容