# State
大多数时候,state
是Store
的中心部分。人们通常从定义应用程序的state
开始。在Pinia
中,state
被定义为一个返回初始state
的函数。这保证了Pinia
在服务器端和客户端都能使用。
import { defineStore } from 'pinia'
const useStore = defineStore('storeId', {
// arrow function recommended for full type inference
state: () => {
return {
// all these properties will have their type inferred automatically
counter: 0,
name: 'Eduardo',
isAdmin: true,
}
},
})
TIP
如果您使用
Vue 2
,您在state
中创建的数据应遵循与Vue
实例中data
相同的规则,即state
对象必须是普通的,并且在向其添加新属性时需要调用Vue.set()
。另请参阅:Vue#data (opens new window)
# 访问State
默认情况下,你可以通过Store
实例直接读写state
:
const store = useStore()
store.counter++
# 重置State
您可以通过调用store
上的$reset()
方法将state
重置为初始值:
const store = useStore()
store.$reset()
# 使用Options API
对于以下示例,您可以假设创建了以下store
:
// Example File Path:
// ./src/stores/counterStore.js
import { defineStore } from 'pinia'
const useCounterStore = defineStore('counterStore', {
state: () => ({
counter: 0
})
})
# 使用setup()
虽然Composition API
并不适合所有人,但是setup()
钩子可以让Pinia
更容易在Options API
中使用。不需要额外的辅助函数!
import { useCounterStore } from '../stores/counterStore'
export default {
setup() {
const counterStore = useCounterStore()
return { counterStore }
},
computed: {
tripleCounter() {
return counterStore.counter * 3
},
},
}
# 不使用setup()
如果您不使用Composition API
,而您使用的是computed
, methods
,…,则你可以使用mapState()
辅助函数将状态属性映射为只读计算属性:
import { mapState } from 'pinia'
import { useCounterStore } from '../stores/counterStore'
export default {
computed: {
// gives access to this.counter inside the component
// same as reading from store.counter
...mapState(useCounterStore, ['counter']),
// same as above but registers it as this.myOwnName
...mapState(useCounterStore, {
myOwnName: 'counter',
// you can also write a function that gets access to the store
double: store => store.counter * 2,
// it can have access to `this` but it won't be typed correctly...
magicValue(store) {
return store.someGetter + this.counter + this.double
},
}),
},
}
# 可修改的 State
如果您希望能够写入这些状态属性(例如,如果您有一个表单),您可以使用mapWritableState()
代替。请注意,您不能像mapState()
那样传递函数:
import { mapWritableState } from 'pinia'
import { useCounterStore } from '../stores/counterStore'
export default {
computed: {
// gives access to this.counter inside the component and allows setting it
// this.counter++
// same as reading from store.counter
...mapWritableState(useCounterStore, ['counter']),
// same as above but registers it as this.myOwnName
...mapWritableState(useCounterStore, {
myOwnName: 'counter',
}),
},
}
TIP 您不需要
mapWritableState()
来处理像数组这样的集合,除非你用cartItems = []
来替换整个数组,mapState()
仍然允许你在你的集合上调用方法。
# 改变 State
除了直接使用store.counter++
改变store
之外,你也可以调用$patch
方法。它允许您使用部分state
对象同时应用到多个改变:
store.$patch({
counter: store.counter + 1,
name: 'Abalam',
})
然而,使用这种语法应用某些改变确实很难或代价高昂:任何集合修改(例如,从数组中添加、删除、修改元素)都需要您创建一个新集合。正因为如此,$patch
方法也接受一个函数来对这种难以应用于patch
对象的改变进行分组:
cartStore.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
这里的主要区别是$patch()
允许您在devtools
中将多个改变分组到一个条目中。注意,对**state
和$patch()
**的直接更改将呈现在devtools
中,并且需要花费些时间(在Vue 3
中还没出现)。
# 替换 State
您可以通过将store
的$state
属性设置一个新对象来替换整个store
的状态:
store.$state = { counter: 666, name: 'Paimon' }
您还可以通过更改 pinia
实例的state
来替换应用程序的整个状态。这在SSR激活 (opens new window)中使用。
pinia.state.value = {}
# 订阅 State
您可以通过store
的$subscribe()
方法查看状态及其变化,这与Vuex
的 subscribe 方法 (opens new window)类似。与常规的watch()
相比,使用$subscribe()
的优势在于,订阅只会在patches
之后触发一次(例如,当使用上面的函数版本时)。
cartStore.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
// same as cartStore.$id
mutation.storeId // 'cart'
// only available with mutation.type === 'patch object'
mutation.payload // patch object passed to cartStore.$patch()
// persist the whole state to the local storage whenever it changes
localStorage.setItem('cart', JSON.stringify(state))
})
默认情况下,状态订阅被绑定到添加它们的组件上(如果store
在组件的setup()
中)。这意味着,当组件被卸载时,它们将被自动删除。如果你想在组件卸载后保留它们,传递{ detached: true }
作为第二个参数来从当前组件中分离状态订阅:
export default {
setup() {
const someStore = useSomeStore()
// this subscription will be kept after the component is unmounted
someStore.$subscribe(callback, { detached: true })
// ...
},
}
TIP 您可以查看`Pinia```实例上的整个状态:
watch(
pinia.state,
(state) => {
// persist the whole state to the local storage whenever it changes
localStorage.setItem('piniaState', JSON.stringify(state))
},
{ deep: true }
)