Initialize Pinia
import { createPinia } from 'pinia'
const pinia = createPinia()
pinia.use(SomePiniaPlugin) // 给 pinia 装插件
const app = createApp(App)
app.use(pinia)
// 这里需要注意时间顺序:只有在调用 app.use(pinia) 之后才能调用 useXxxStore()
复制代码
Use Store
- defineStore accepts an id, the id of different data sources must be different
- The return value of useCounter() cannot be destructured, which will result in the loss of data responsiveness
// src/stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counterStore', {
state: ()=> {
return {j: 0, k: 0}
}
})
// counter.js
import { useCounterStore } from 'path/to/src/stores/counterStore'
export default {
setup() {
const counterStore = useCounterStore()
// 这里在视图里使用 counterStore.j 和 counterStore.k
// 但你不能解构 counterStore,只能像下面这样解构:
const { j, k } = storeToRefs(counterStore)
return {
counterStore, j, k,
}
},
}
复制代码
Store Getters
Getters is actually a collection of computed properties of the store, and getters cannot be asynchronous functions
export const useStore = defineStore('main', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount(state) {
return state.counter * 2
},
doublePlusOne(): number {
return this.doubleCount + 1 // getter 访问另一个 getter 可以用 this
},
getUserById: (state) => { // getter 可以返回一个函数,不过这会导致缓存失效
return (userId) => state.users.find((user) => user.id === userId)
},
otherGetter(state) { // 你还可以调用其他的 store
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
// store.doubleCount 和 store.doublePlusOne 就可以直接当做属性使用了
// store.getUserById(userId) 可以当做函数使用
复制代码
Store Actions
Action is actually the methods of the store, and it can be an asynchronous function
export const useUserStore = defineStore('users', {
state: () => ({
userData: null,
}),
actions: {
async signUp(email, password) {
this.userData = await api.post({ email, password }).catch(error => {
showError(error); throw error;
})
},
},
})
// 然后你就可以使用 userStore.signUp(email, password) 了
复制代码
store.$patch(object | fn)
counterStore.$patch(
{j: counterStore.j + 1, name: 'j加1'}
)
cartStore.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
复制代码
store.$subscribe(fn)
Used to monitor overall changes in state.
cartStore.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
mutation.storeId
mutation.payload // 获取 $patch 接收到的参数
localStorage.setItem('cart', JSON.stringify(state))
})
复制代码
It has a very convenient feature that it will automatically log out when the component is unloaded. If you don't want it, you can pass an {detached: true}
option .
You can also use watch to achieve a similar effect:
watch(
pinia.state,
(state) => {
localStorage.setItem('piniaState', JSON.stringify(state))
},
{ deep: true }
)
复制代码
store.$onAction()
Used to monitor the execution of all actions.
const unsubscribe = someStore.$onAction(
({
name, // action 的名字
store, // store === someStore
args, // action 的实际参数
after, // action 成功之后执行 after
onError, // action 失败之后执行 onError
}) => {
const startTime = Date.now()
console.log(`开始执行 "${name}" 参数为 [${args.join(', ')}].`)
after((result) => {
console.log(
`执行成功 "${name}" 用时 ${Date.now() - startTime}毫秒\n结果为:${result}`
)
})
onError((error) => {
console.warn(
`执行失败 "${name}" 用时 ${Date.now() - startTime}毫秒\n报错为:${error}.`
)
})
}
)
// $onAction 会在它所在组件卸载时自动销毁
// 如果你将 $onAction 的第二个参数设置为 true,那么你需要自己调用 unsubscribe 来取消监听。
复制代码
store.$reset()
You can reset the state with counterStore.$reset()
store.$state
// 下面两句代码都能覆盖原有 state
store.$state = { counter: 666, name: 'Paimon' }
pinia.state.value = {} // 这句常用在 SSR
复制代码