輕量級狀態管理庫Pinia試吃


  最近連續看了幾個GitHub上的開源項目,里面都用到了 Pinia 這個狀態管理庫,於是研究了一下,發現確實是個好東西!那么,Pinia 的特點:

  • 輕量化 —— Pinia 體積約1KB,十分輕巧,加載運行都很快速,相對來說Vuex明顯塊頭更大一些
  • Pinia 的 API 設計並非追求另辟蹊徑,事實上它十分接近 Vuex 5的提案,並且對composition API非常友好(作者本身是Vue.js的核心成員,並且積極參與Vue Router以及Vuex的API設計)
  • 模塊化設計,支持創建數個store(有點類似Vuex中的module),在打包時會被自動拆分
  • 跨模塊調用十分直觀方便,你可以在任意的 store 之間交叉組合使用
  • 完美支持Typescript,不得不說這個是Vuex的最大劣勢之一,深度使用過Vuex + Ts的童鞋應該都懂
  • 可脫離組件使用,比如在編寫router時調用
  • Vue devtools兼容(暫不支持個別功能點)
  • 同時支持Vue2/Vue3

  具體的使用細節就不照搬文檔了,官網鏈接奉上 => Pinia
  值得一提的是,雖然文檔使用英文編寫,但是文檔結構、語言組織等方面都屬上乘,通俗易懂

  下面介紹幾個亮點特性。

一、結構設計與Vuex API非常相似

這使得它學習成本很低,如果之前使用過Vuex的話,可以非常方便的上手

import { defineStore } from 'pinia'

interface AppState {
  name: string;
}

export const useUserStore = defineStore({
  id: 'app',
  state: (): AppState =>({
    name: 'Eduardo'
  }),
  getters: {},
  actions: {}
})

二、取消mutation,使用三種方式更改state

<script lang="ts" setup>
import { useStore } from '@/store/modules/app';
import { ref } from 'vue';

const store = useStore();

function raise() {
  // 方式一:直接修改 -> 'direct'
  store.salary += 10000;

  // 方式二:patch對象 -> 'patch object',填入打算更改的state字段即可
  store.$patch({
    salary: store.salary + 10000,
  });

  // 方式三:patch函數 -> 'patch function',可鍵入語句,執行復雜邏輯
  store.$patch((state) => {
    state.salary += 10000;
  });
}
</script>

三、store使用reactive包裹,自帶響應性

無需二次包裹reactive、computed,即可在模板中直接使用,同時具有響應性

<template>
  <div>{{ store.name }}, 文章閱讀量:{{ store.article }}</div>
  <hr />
  <button @click="jump">點擊跳轉閱讀新文章</button>
</template>

四、跨模塊調用直觀方便

直接引入其他store的hook函數,調用即可

import { useSomeOtherStore } from './auth-store'

export const useAppStore = defineStore('app', {
  state: () => ({
    // ...
  }),
  actions: {
    async someAction() {
      const someOtherStore = useSomeOtherStore()
      // ...
    },
  },
})

五、組件外調用

用戶創建的類似useStore這樣的Hook函數默認會自動注入在單頁應用入口處創建並傳遞給app實例的Pinia實例(有點拗口...),在組件內使用時,Pinia實例肯定已經傳遞給app實例了,這時候直接調用hook函數使用就完事了。但在組件外使用時,很可能出現在調用hook函數時,Pinia實例還未傳遞給app實例,這時候就需要用戶手動將Pinia實例傳入hook函數,並暴露出來以供調用。具體可參見官方文檔的對應章節 -> Using a store outside of a component

// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import { pinia } from '@/store'

const app = createApp(App)
// 將pinia實例傳遞給app實例,在此之后使用useStore鈎子,會自動注入pinia實例,否則需要在useStore中手動注入
app.use(pinia)

app.mount('#app')

// store/index.ts
import { createPinia } from 'pinia'

const pinia = createPinia()
export { pinia }

// store/modules/app.ts
import { defineStore } from 'pinia'
import { pinia } from '@/store'

interface AppState {
  name: string;
}

export const useUserStore = defineStore({
  id: 'app',
  state: (): AppState =>({
    name: 'Eduardo'
  }),
  getters: {},
  actions: {}
})

// 這里的pinia即為通過createPinia()生成並在入口處傳遞給app實例的pinia實例,在此手動注入,並暴露
export function useAppStoreHook() {
  return useAppStore(store)
}

最后,推薦大家嘗試,真的好用~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM