<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          全新的 Vue3 狀態(tài)管理工具:Pinia

          共 3582字,需瀏覽 8分鐘

           ·

          2021-12-16 22:37

          Vue3 發(fā)布已經(jīng)有一段時(shí)間了,它采用了新的響應(yīng)式系統(tǒng),而且構(gòu)建了一套全新的 Composition API。Vue 的周邊生態(tài)都在加緊適配這套新的系統(tǒng),官方的狀態(tài)管理庫 Vuex 也在適配中,為此官方提出了一個(gè) Vuex 5 的全新提案。

          • 支持兩種語法創(chuàng)建 Store:Options ApiComposition Api
          • 刪除 mutations,只支持 stategettersactions
          • 模塊化的設(shè)計(jì),能很好支持代碼分割;
          • 沒有嵌套的模塊,只有 Store 的概念;
          • 完整的 TypeScript 支持;

          在這個(gè)提案下方,有個(gè)評(píng)論很有意思。簡單翻譯一下:

          好巧不巧,Vuex5 的提案,與 Pinia 實(shí)現(xiàn)的功能不能說毫無關(guān)系,只能說一模一樣,今天的文章就來給大家介紹一下這個(gè)菠蘿。

          安裝

          在現(xiàn)有項(xiàng)目中,用過如下命令進(jìn)行 Pinia 模塊的安裝。

          #?yarn
          yarn?add?pinia@next
          #?npm
          npm?i?pinia@next

          安裝完成后,需要在 Vue3 項(xiàng)目的入口文件中,進(jìn)行導(dǎo)入安裝。

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

          //?實(shí)例化?Vue
          const?app?=?createApp(App)
          //?安裝?Pinia
          app.use(createPinia())
          //?掛載在真實(shí)?DOM
          app.mount('#app')

          上手

          要使用 Pinia 的話,只需要定義一個(gè) store,然后在用到該數(shù)據(jù)的地方進(jìn)行導(dǎo)入。

          定義 Store

          import?{?defineStore?}?from?"pinia"

          //?對(duì)外部暴露一個(gè)?use?方法,該方法會(huì)導(dǎo)出我們定義的?state
          const?useCounterStore?=?defineStore({
          ??//?每個(gè)?store?的?id?必須唯一
          ??id:?'counter',
          ??//?state?表示數(shù)據(jù)源
          ??state:?()?=>?({
          ????count:?0
          ??}),
          ??//?getters?類似于?computed,可對(duì)?state?的值進(jìn)行二次計(jì)算
          ??getters:?{
          ????double?()?{
          ?????//?getter?中的?this?指向???state
          ?????return?this.count?*?2
          ???},
          ???//?如果使用箭頭函數(shù)會(huì)導(dǎo)致?this?指向有問題
          ???//?可以在函數(shù)的第一個(gè)參數(shù)中拿到?state
          ????double:?(state)?=>?{
          ?????return?state.count?*?2
          ???}
          ??},
          ??//?actions?用來修改?state
          ??actions:?{
          ????increment()?{
          ??????//?action?中的?this?指向???state
          ??????this.count++
          ????},
          ??}
          })

          export?default?useCounterStore

          除了使用上述類似 vuex 的方式來構(gòu)建 state,還可以使用 function 的形式來創(chuàng)建 store,有點(diǎn)類似于 Vue3 中的 setup()

          import?{?ref,?computed?}?from?"vue"
          import?{?defineStore?}?from?"pinia"

          //?對(duì)外部暴露一個(gè)?use?方法,該方法會(huì)導(dǎo)出我們定義的?state
          const?useCounterStore?=?defineStore('counter',?function?()?{
          ??const?count?=?ref(0)
          ??const?double?=?computed(()?=>?count.value?*?2)
          ??function?increment()?{
          ????count.value++
          ??}
          ??return?{
          ???count,?double,?increment
          ??}
          })

          export?default?useCounterStore

          使用 Store

          前面也介紹過,Pinia 提供了兩種方式來使用 store,Options ApiComposition Api 中都完美支持。

          Options Api

          Options Api 中,可直接使用官方提供的 mapActionsmapState 方法,導(dǎo)出 store 中的 state、getter、action,其用法與 Vuex 基本一致,很容易上手。

          import?{?mapActions,?mapState?}?from?'pinia'
          import?{?useCounterStore?}?from?'../model/counter'

          export?default?{
          ??name:?'HelloWorld',
          ??computed:?{
          ????...mapState(useCounterStore,?['count',?'double'])
          ??},
          ??methods:?{
          ????...mapActions(useCounterStore,?['increment'])
          ??}
          }

          Composition Api

          Composition Api 中,不管是 state 還是 getter 都需要通過 computed 方法來監(jiān)聽變化,這和 Options Api 中,需要放到 computed 對(duì)象中的道理一樣。另外, Options Api ?中拿到的 state 值是可以直接進(jìn)行修改操作的,當(dāng)然還是建議寫一個(gè) action 來操作 state 值,方便后期維護(hù)。

          //?Composition?Api
          import?{?computed?}?from?'vue'
          import?{?useCounterStore?}?from?'../stores/counter'
          export?default?{
          ??name:?'HelloWorld',
          ??setup()?{
          ????const?counter?=?useCounterStore()
          ????return?{
          ??????//?state?和?getter?都需要在使用?computed,這和?Options?Api?一樣
          ??????count:?computed(()?=>?counter.count),
          ??????double:?computed(()?=>?counter.double),
          ??????increment:?()?=>?{?counter.count++?},?//?可以直接修改?state?的值
          ??????increment:?counter.increment,?//?可以引用?store?中定義的?action
          ????}
          ??}
          }

          類型提示

          在 Vuex 中,TypeScript 的類型提示做得不是很好,在進(jìn)行類型推導(dǎo)時(shí),只能找到它的 state。特別是寫代碼的過程中,代碼提示就很不智能。

          而 pinia,就能推導(dǎo)出定義的所有 state、getter、action,這樣在寫代碼的時(shí)候,就會(huì)方便很多。

          主要是 pinia 通過 TypeScript 進(jìn)行了十分友好的類型定義,感興趣的可以看看 pinia 的類型定義文件(pinia.d.ts):

          代碼分割

          由于使用了模塊化設(shè)計(jì),所有的 store 都能夠單獨(dú)引入,而不是像 vuex 一樣,通過 modules 的方式,將所有的 module 掛載到一個(gè) store 上。

          假設(shè),我們當(dāng)前通過 Vuex 創(chuàng)建了一個(gè) Store,這個(gè) Store 下有兩個(gè) module,分別是用戶模塊(User)和商品模塊(Goods)。即使當(dāng)前首頁只使用到了用戶信息,但是整個(gè) Store 都會(huì)被打包到首頁的 js chunk 中。

          如果我們使用 pinia,我們會(huì)使用 defineStore 定義兩個(gè) 完全是分離狀態(tài)的 store,兩個(gè)頁面在引入時(shí),也互不影響。最后打包的時(shí)候,首頁的 js chunk 和商品頁的 js chunk 會(huì)分別打包對(duì)應(yīng)的 store。


          Pinia 的介紹到這里就告一段落了,如果現(xiàn)在有新項(xiàng)目要使用 Vue3 進(jìn)行開發(fā),推薦無腦使用 Pinia,更加簡潔,而且大小僅 1KB。

          - END -


          瀏覽 102
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青操av在线 | 无码人妻一区二区三区四区老鸭窝 | 国产小视频在线 | 超碰青娱乐91 | 九九成人网站 |