一個替代vuex的輕量級好用方案,真香。
引入
#main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
pinia的store
#counter.js
import { defineStore } from 'pinia'
function getNewDiscountRate(rate) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(rate * Math.random())
}, 1000)
})
}
export const useCounterStore = defineStore({
id: 'counter',
state: () => ({
counter: 0,
name: 'jason',
discountRate:10
}),
getters: {
// 方法一
doubleCount: (state) => { state.counter * 2 },
// 方法二想用this(可以獲取整個實例)不能用箭頭函式
doubleCountByRowFunc: function () { return this.counter * 2 }
},
actions: {
// func
increment() {
this.counter++
},
// asyn func
async changeDiscountRate() {
try {
return this.discountRate = await getNewDiscountRate(this.discountRate)
} catch (e) {
throw Error(e)
}
}
}
})
使用
<template>
<div class="about">
<h1>This is an about page</h1>
{{ counter }}
<br />
{{ doubleCount }}
<br />
{{ name }}
<button @click="counter++">直接改</button>
<button @click="clickPatch">用$patch改</button>
<button @click="clickState">用$state改</button>
</div>
</template>
<script setup>
import { useCounterStore } from '../stores/counter.js'
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// 使用
let { counter, doubleCount, name } = storeToRefs(store)
function clickPatch() {
// 更改寫法一
// store.$patch({
// counter: counter.value + 1
// })
// 更改寫法二
store.$patch((state) => {
state.counter += 1
})
}
//更改寫法三
function clickState() {
store.$state = { name: '123' }
}
// 監聽
// 參數一是監聽時候執行的func 參數二是組件銷毀後是否繼續保持監聽預設會自動解除監聽
store.$subscribe((mutation,state)=>{
console.log(mutation,state)
},true)
// 監聽action回傳promise時候進入after但是要記得再pinia return出來才接的到形參 回傳throw時候進入或是promise reject的時候
store.$onAction(
({
name,
store,
args,
after,
onError,
}) => {
const startTime = Date.now()
console.log(`Start "${name}" with params [${args.join(', ')}].`)
after((result) => {
console.log(
`Finished "${name}" after ${
Date.now() - startTime
}ms.\nResult: ${result}.`
)
})
onError((error) => {
console.warn(
`Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
)
})
}
)
setTimeout(()=>{
store.changeDiscountRate()
},1000)
</script>
<style>
@media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>
簡單總結
若想要解構出所有store屬性並且保持綁定要使用storeToRefs
改store值方法有
store.$patch(obj)
store.$patch((state)=>(state.xxx=xxx))
store.xxx = xxx
store.$store({})
監聽值
store.$subscribe((mu,state)=>{},boolean)
監聽action
store.$onAction((ctx)=>{},boolean)
重新初始化store
store.$reset()