Pinia快速入門-上手指南

Pinia是什么

PiniaVue 的存儲庫,允許您跨組件/頁面共享狀態(tài)。Pinia 這款產品最初是為了探索 Vuex 的下一個版本,整合了核心團隊關于 Vuex 5 的許多想法。最終,我們意識到 Pinia 已經實現(xiàn)了我們想要在 Vuex 5 中提供的大部分內容,因此決定將其作為 新的官方推薦

Pinia特點

  • 足夠輕量,Pinia 重約 1kb,甚至會忘記它的存在!
  • 去除 MutationActions 支持同步和異步(Actions一個頂倆,寫起來簡潔);
  • 無需手動注冊 Store,Store 僅需要時才自動注冊。如果從不使用,則永遠不會“注冊”(省心);
  • 沒有模塊嵌套,只有 Store 的概念,Store 之間可以自由使用,更好的代碼分割;
  • Vue2Vue3 都能支持;
  • 支持大型項目遷移期間,PiniaVuex 混合使用(貼心遷移);
  • 更完美的 typescript 的支持;
  • Vue devtools 掛鉤,Vue2 和 Vue3 開發(fā)體驗更好;
  • 支持插件擴展功能;
  • 支持模塊熱更新,無需加載頁面可以修改容器,可以保持任何現(xiàn)有的狀態(tài);
  • 支持服務端渲染;

VuexPinia 用哪個

Vuex 現(xiàn)在處于維護模式。它仍然可以工作,但不再添加新的功能。對于新的應用項目,建議使用 Pinia。Pinia 已經實現(xiàn)了我們想要在 Vuex 5 中提供的大部分內容,因此決定將其作為 新的官方推薦(注意:舊版網(wǎng)站沒有更新)

如何使用 Pinia

一、安裝

npm install pinia

vue2需要另外安裝

npm i pinia @vue/composition-api --save

二、定義 Store

新建 src/stores 目錄并在其下面創(chuàng)建 index.ts

Pinia 的目錄通常被稱為 stores 而不是 store, 這是為了強調 Pinia 使用多個 store,而不是 Vuex 中的單個 store,同時也有遷移期間 PiniaVuex 混合使用的考慮。

// src/stores/index.ts
// 引入Store定義函數(shù)
import { defineStore } from 'pinia'

// 定義Store實例并導出,useStore可以是任何東西,比如useUser, useCart
// 第一個參數(shù),唯一不可重復,字符串類型,作為倉庫ID 以區(qū)分倉庫
// 第二個參數(shù),以對象形式配置倉庫的state,getters,actions
export const useStore = defineStore('main', {
  // state 推薦箭頭函數(shù),為了TS類型推斷
  state: () => {
    return {
      name: '張三',
      counter: 0
    }
  },
  getters: {},
  actions: {}
})

在 main.ts 中引入并掛載到根實例。

// src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
// 創(chuàng)建Vue應用實例
// 實例化 Pinia
// 以插件形式掛載Pinia實例
createApp(App).use(createPinia()).mount('#app')

vue2寫法

定義store同vue3,main.js中引入并掛在到跟實例代碼如下:

//main.js引入
// 引入pinia
import {createPinia,PiniaVuePlugin} from 'pinia'
Vue.use(PiniaVuePlugin)
const pinia = createPinia()//需要掛載在實例上

new Vue({
  router,
  pinia,
  render: h => h(App)
}).$mount('#app')

vue2中如果報如下錯誤,


則需要在vue.config.js中增加以下配置:


三、State

1、訪問State

<template>
  <div>
     <button @click="handleClick">修改狀態(tài)數(shù)據(jù)</button>
     <!-- 模板內不需要加.value -->
     <p>{{store.name}}</p>
     <!-- computed獲取 -->
     <p>{{name}}</p>
     <!-- 或者使用解構之后的 -->
     <p>{{counter}}</p>
  </div>
</template>

<script lang="ts" setup>
import { useStore } from '@/stores/index.ts'
// 使普通數(shù)據(jù)變響應式的函數(shù)  
import { storeToRefs } from "pinia";

const store = useStore()

// 結合computed獲取
const name = computed(() => store.name)
// 解構并使數(shù)據(jù)具有響應式
const { counter } = storeToRefs(store);

// 點擊 + 1;
function handleClick() {
  // ref數(shù)據(jù)這里需要加.value訪問
  counter.value++;
}
</script>

2、修改State

1、單個參數(shù)修改 state

store.counter++

2、多個參數(shù)修改 state

store.$patch({
  counter: store.counter + 1,
  name: 'Abalam',
})

3、全部修改 state

store.$state = { counter: 666, name: 'Paimon' }
或
pinia.state.value = {}

3、重置State

將狀態(tài)重置為初始值

const store = useStore()
store.$reset()

4、vue2寫法

import { mapState } from 'pinia'
import { useCounterStore } from '../stores/counterStore'

export default {
  computed: {
    ...mapState(useCounterStore, ['counter'])
    // 或
    ...mapState(useCounterStore, {
      myOwnName: 'counter',
      double: store => store.counter * 2,
      magicValue(store) {
        return store.someGetter + this.counter + this.double
      },
    }),
  },
}

四、Getters

getter 中的值有緩存特性,類似于computed,如果值沒有改變,多次使用也只會調用一次

1、定義Getters:

export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  getters: {
    doubleCount: (state) => state.counter * 2,
    // 自動推導返回類型
    doubleCount(state) {
      return state.counter * 2
    },
    // 依賴getters返回參數(shù),則需要顯性的設置返回類型
    doublePlusOne(): number {
      return this.doubleCount + 1
    },
  },
})

2、使用Getters

<template>
  <p>Double count is {{ store.doubleCount }}</p>
</template>

<script>
export default {
  setup() {
    const store = useStore()
    
    return { store }
  },
}
</script>

3、vue2寫法

import { mapState } from 'pinia'
import { useCounterStore } from '../stores/counterStore'

export default {
  computed: {
    ...mapState(useCounterStore, ['doubleCount'])
    // 或
    ...mapState(useCounterStore, {
      myOwnName: 'doubleCounter',
      double: store => store.doubleCount,
    }),
  },
}

五、Actions

Pinia 中刪除了 Mutation,Actions 支持同步和異步

1、定義 Actions

// 同步
export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
    userData: null,
  }),
  actions: { 
    increment() {
      this.counter++
    },
    randomizeCounter() {
      this.counter = Math.round(100 * Math.random())
    },
  },
})
// 異步
import { mande } from 'mande'
const api = mande('/api/users')

export const useUsers = defineStore('users', {
  state: () => ({
    userData: null,
  }),

  actions: {
    async registerUser(login, password) {
      this.userData = await api.post({ login, password })
    },
  },
})

2、調用 Actions

1、可以直接調用 store 的任何方法

<script>
export default {
  setup() {
    const store = useStore()
    store.randomizeCounter()
  },
}
</script>

2、action 間的相互調用,直接用 this 訪問即可。

 export const useUserStore = defineStore({'user',
  actions: {
    increment() {
      this.counter++
    },
    increase() {
      // 調用另一個 action 的方法
      this.increment()
    },
  }
})

3、在 action 里調用其他 store 里的 action 也比較簡單,引入對應的 store 后即可訪問其內部的方法。

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

export const useSettingsStore = defineStore('settings', {
  state: () => ({
    preferences: null,
  }),
  actions: {
    async fetchUserPreferences() {
      // 調用 auth-store store 里的 action 方法
      const auth = useAuthStore()
      if (auth.isAuthenticated) {
        this.preferences = await fetchPreferences()
      } else {
        throw new Error('User must be authenticated')
      }
    },
  },
})

3、vue2寫法

import { mapActions } from 'pinia'
import { useCounterStore } from '../stores/counterStore'

export default {
  methods: {
    ...mapActions(useCounterStore, ['increment'])
    // 或
    ...mapActions(useCounterStore, { myOwnName: 'doubleCounter' }),
  },
}

總結

總得來說,Pinia 就是 Vuex 的官方替代版,可以更好的支持 Vue2,Vue3以及TypeScript。在 Vuex 的基礎上去掉了 Mutation、模塊嵌套等概念,語法更簡潔直接, 更符合 Vue3 的 Composition api,為 TypeScript 提供了更好的類型推導。以上是 Pinia.js 用法的一些介紹,Pinia.js 的內容還遠不止這些,更多內容及使用有待大家自己探索。Pinia文檔

參考文章:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容