# Pinia入門
###### tags: `pinia`
參考
- [Pinia - Vuex 的後繼者]((https://johnnywang1994.github.io/book/articles/js/pinia-intro.html#install))
- [Pinia 快速入門](https://blog.csdn.net/wx_15896014638/article/details/118931645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164724218316780274111752%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164724218316780274111752&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-118931645.article_score_rank&utm_term=Pinia&spm=1018.2226.3001.4187)
- [還在用vuex嗎,pinia(菠蘿頭)才香](https://blog.csdn.net/weixin_42232622/article/details/122811173?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&utm_relevant_index=2)
- [拥抱pinia,快速上手,详解指南](https://juejin.cn/post/7063376847198748702)
## vuex4缺點
- 改變一個`state`的值,如果是更新需要定義`mutations`和`actions`,並且使用`dispatch`調用
- ==添加typescript需要自定義復雜的類型來支持ts==
- 想把state分成多個部分,就需要用到 module(定義module很麻煩)
- 從vue3開始。 `getters`的結果不會像計算屬性那樣緩存了
- 模塊間嚴重嵌套(例如..mapState({a: state => state.some.nested.module.a)
## Pinia優點
- ==完整的 `TypeScript` 支持;天生具備完美的類型推斷==
- 支持兩種語法創建 Store:Options Api 和 Composition Api
- 可以構建多個store,打包管理會自動拆分
- **模塊化的設計**,便於拆分狀態,能很好支持代碼分割;
- ++沒有嵌套的模塊,可以聲明多個Store++ ,且仍然能夠在存儲空間之間進行交叉組合
- 沒有命名空間的模塊( `namespaced`模塊),可以說是所有的store都是獨立的`module`
- 輕巧, 僅有 1 KB
- 支持Vue DevTools, SSR和Webpack 代碼拆分
- 無論是Vue2或是Vue3都可以使用,**且不一定要與 Composition API 一起使用**,API 的使用方式在兩者中也是保持一致的。
## Pinia vs. Vuex
- 移除 Mutations
- Typescript 不再需要多餘的 types 來包裝
- 不再需要引入各種 [magic string](https://developer.aliyun.com/ask/259483),直接引入函數,享受自動補全帶來的快樂
- 不再需要動態註冊模組,預設都是動態註冊
- 拋棄 Nested Module(巢狀module)
- 無痛產store module
- [vuex4入門](https://hackmd.io/@Yan06/Bkc2FVZQ5)
### install
```
yarn add pinia
```
### 創建store
in store/index.js
```javascript=
import { createPinia } from 'pinia';
// 創建 pinia
const pinia = createPinia();
export default pinia;
```
in main.js
```javascript=
import { createApp } from 'vue';
import App from './App.vue';
import pinia from './store';
const app = createApp(App);
// 綁定 pinia 到 app
app.use(pinia);
app.mount('#app');
//
```
### 創建module
引入 defineStore 方法,Options 與 Vuex 除了 mutations 以外基本相同,包含 state, getters, actions
```javascript=
import { defineStore } from 'pinia';
// 這邊 defineStore 會自動動態註冊模組,回傳值為 hook function
export const useDemoStore = defineStore('Main', {
// 注意 state 是一個 function,推薦使用 arrow function
// 可幫助 typescript 更好進行類型推斷
state: () => {
return {
count: 100,
quantity: 10
};
},
getters: {
countTotal: (state) => state.count * state.quantity
},
actions: {
countChange: (val) => {
console.log(val, 'action中的參數');
this.count ++
this.quantity ++
//or
// this.$patch({})
// this.$patch(state => {})
}
},
})
```
### 在組件中使用
```javascript=
//app.vue
import { useDemoStore } from '@/store/main.js'
import { storeToRefs, mapState } from 'pinia'
import { computed } from 'vue';
const demoStore = useDemoStore()
const { countChange } = demoStore
//可以這樣拿(解構)
// const { count, quantity, countTotal } = storeToRefs(demoStore)
//也可以像是vuex一樣的拿法
computed(() => {
return {
...mapState(useDemoStore, ['count', 'quantity', 'countTotal']),
}
})
//修改state中的數據
const demoStoreChange = () => {
demoStore.$patch(state => {
state.count++
state.quantity++
})
//邏輯較多時 可以寫在actions裡 直接調用
// countChange()
}
//in html記得要用demoStore去拿裡面的東西
<p>count: {{ demoStore.count }}</p>
<p>quantity: {{ demoStore.quantity }}</p>
<p>count total: {{ demoStore.countTotal }}</p>
```