入门指南
核心概念
服务端渲染
开发者指南
- Migrating from Vuex ≤4
- HMR (Hot Module Replacement)
- 测试存储商店
- Usage without setup()
- Composing Stores
- Migrating from 0.x (v1) to v2
API 手册
- API Documentation
- Module: pinia
- Module: @pinia/nuxt
- Module: @pinia/testing
- Enumeration: MutationType
- Interface: TestingOptions
- Interface: DefineSetupStoreOptions
- Interface: DefineStoreOptions
- Interface: DefineStoreOptionsBase
- Interface: DefineStoreOptionsInPlugin
- Interface: MapStoresCustomization
- Interface: Pinia
- Interface: PiniaCustomProperties
- Interface: PiniaCustomStateProperties
- Interface: PiniaPlugin
- Interface: PiniaPluginContext
- Interface: StoreDefinition
- Interface: StoreProperties
- Interface: SubscriptionCallbackMutationDirect
- Interface: SubscriptionCallbackMutationPatchFunction
- Interface: SubscriptionCallbackMutationPatchObject
- Interface: _StoreOnActionListenerContext
- Interface: _StoreWithState
- Interface: _SubscriptionCallbackMutationBase
- Interface: TestingPinia
State
大多数时候,州是商店的中心部分。 人们通常从定义代表他们的应用程序的状态开始。 在 Pinia 中,状态被定义为返回初始状态的函数。 这允许 Pinia 在服务器端和客户端工作。
jsimport { defineStore } from 'pinia'
export const useStore = defineStore('storeId', {
// 推荐用于完整类型推断的箭头函数
state: () => {
return {
// 所有这些属性都将自动推断其类型
count: 0,
name: 'Eduardo',
isAdmin: true,
items: [],
hasChanged: true,
}
},
})
TIP
如果您使用的是 Vue 2,您在 state
中创建的数据遵循与 Vue 实例中的 data
相同的规则,即 state 对象必须是普通的,并且您需要在以下情况下调用 Vue.set()
*为其添加新的**属性。 另请参阅:Vue#data。
TypeScript
为了使您的状态与 TS 兼容,您不需要做太多事情:确保 strict
,或者至少,noImplicitThis
,已启用,Pania 将自动推断您的状态类型! 但是,在某些情况下,您应该帮助它进行一些铸造:
export const useUserStore = defineStore('user', {
state: () => {
return {
// 对于最初为空的列表
userList: [] as UserInfo[],
// 对于尚未加载的数据
user: null as UserInfo | null,
}
},
})
interface UserInfo {
name: string
age: number
}
如果您愿意,可以使用接口定义状态并输入 state()
的返回值:
interface State {
userList: UserInfo[]
user: UserInfo | null
}
export const useUserStore = defineStore('user', {
state: (): State => {
return {
userList: [],
user: null,
}
},
})
interface UserInfo {
name: string
age: number
}
访问state
默认情况下,您可以通过 store
实例访问状态来直接读取和写入状态:
const store = useStore()
store.count++
注意你不能添加一个新的状态属性如果你没有在state()
中定义它,它必须包含初始状态。 例如:如果 state()
中没有定义 secondCount
,我们就不能执行 store.secondCount = 2
。
重置状态
您可以通过调用 store 上的 $reset()
方法将状态 reset 到其初始值:
const store = useStore()
store.$reset()
使用选项式 API
对于以下示例,您可以假设已创建以下商店:
js// Example File Path:
// ./src/stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
})
如果您不使用 Composition API,并且使用的是 computed
、methods
、...,则可以使用 mapState()
帮助器将状态属性映射为只读计算属性:
import { mapState } from 'pinia'
import { useCounterStore } from '../stores/counter'
export default {
computed: {
// 提供对组件内部 this.count 的访问
// 与从 store.count 读取相同
...mapState(useCounterStore, ['count'])
// 与上面相同,但将其注册为 this.myOwnName
...mapState(useCounterStore, {
myOwnName: 'count',
// 您还可以编写一个访问商店的函数
double: store => store.count * 2,
// 它可以访问“this”,但不能正确输入...
magicValue(store) {
return store.someGetter + this.count + this.double
},
}),
},
}
可修改状态
如果您希望能够写入这些状态属性(例如,如果您有一个表单),您可以使用 mapWritableState()
代替。 请注意,您不能传递类似于 mapState()
的函数:
import { mapWritableState } from 'pinia'
import { useCounterStore } from '../stores/counter'
export default {
computed: {
// 允许访问组件内部的 this.count 并允许设置它
// this.count++ 与从 store.count 中读取相同
...mapWritableState(useCounterStore, ['count'])
// 与上面相同,但将其注册为 this.myOwnName
...mapWritableState(useCounterStore, {
myOwnName: 'count',
}),
},
}
TIP
对于像数组这样的集合,您不需要 mapWritableState()
,除非您用 cartItems = []
替换整个数组,mapState()
仍然允许您调用集合上的方法。
改变状态
除了直接用 store.count++
修改 store,你还可以调用 $patch
方法。 它允许您使用部分“状态”对象同时应用多个更改:
store.$patch({
count: store.count + 1,
age: 120,
name: 'DIO',
})
但是,使用这种语法应用某些突变非常困难或代价高昂:任何集合修改(例如,从数组中推送、删除、拼接元素)都需要您创建一个新集合。 正因为如此,$patch
方法也接受一个函数来分组这种难以用补丁对象应用的突变:
store.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
这里的主要区别是$patch()
允许您将多个更改分组到开发工具中的一个条目中。 注意两者,state
和 $patch()
的直接更改都出现在 devtools 中,并且可以进行时间旅行(在 Vue 3 中还没有)。
替换状态
您不能完全替换 store 的状态,因为这会破坏反应性。 但是,您可以_patch it_:
js// 这实际上并没有取代`$state`
store.$state = { count: 24 }
// 它在内部调用`$patch()`:
store.$patch({ count: 24 })
您还可以通过更改 pinia
实例的 state
来设置整个应用程序的初始状态。 这在 SSR 水合 期间使用。
pinia.state.value = {}
订阅状态
可以通过 store 的 $subscribe()
方法查看状态及其变化,类似于 Vuex 的 subscribe 方法。 与常规的 watch()
相比,使用 $subscribe()
的优点是 subscriptions 只会在 patches 之后触发一次(例如,当使用上面的函数版本时)。
cartStore.$subscribe((mutation, state) => {
// 从'pinia'导入{ MutationType }
mutation.type // 'direct' | 'patch object' | 'patch function'
// 与 cartStore.$id 相同
mutation.storeId // 'cart'
// 仅适用于 mutation.type === 'patch object'
mutation.payload // 传递给 cartStore.$patch() 的补丁对象
// 每当它发生变化时,将整个状态持久化到本地存储
localStorage.setItem('cart', JSON.stringify(state))
})
默认情况下,state subscriptions 绑定到添加它们的组件(如果商店位于组件的 setup()
中)。 意思是,当组件被卸载时,它们将被自动删除。 如果您还想在组件卸载后保留它们,请将 { detached: true }
作为第二个参数传递给 detach 当前组件的 state subscription:
export default {
setup() {
const someStore = useSomeStore()
// 即使在卸载组件后,此订阅仍将保留
someStore.$subscribe(callback, { detached: true })
// ...
},
}
TIP
您可以在 pinia
实例上查看整个状态:
watch(
pinia.state,
(state) => {
// 每当它发生变化时,将整个状态持久化到本地存储
localStorage.setItem('piniaState', JSON.stringify(state))
},
{ deep: true }
)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论