Pinia
# Pinia
Pinia 是一个Vue.js 状态管理库。
# 一、定义 Store
Pinia 的 Store 是用 defineStore
方法定义的。 其参数需要给 Store 起个名字。
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
2
3
4
5
6
7
8
9
10
11
state
是 store 的 数据 ,getters
是 store 的 计算属性,- 而
actions
则是 方法 。
# 二、使用 Store
虽然我们前面定义了一个 store,但在我们使用 <script setup>
调用 useStore()
(或者使用 setup()
函数,像所有的组件那样 之前,store 实例是不会被创建的:
<script setup>
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
</script>
2
3
4
# 三、State
在大多数情况下,state
都是你的 store
的核心。人们通常会先定义能代表他们 APP 的 state。在 Pinia 中,state 被定义为一个返回初始状态的函数。这使得 Pinia 可以同时支持服务端和客户端。
const useStore = defineStore('storeId', {
// 为了完整类型推理,推荐使用箭头函数
state: () => {
return {
// 所有这些属性都将自动推断出它们的类型
count: 0,
name: 'Eduardo',
isAdmin: true,
items: [],
hasChanged: true,
}
},
})
2
3
4
5
6
7
8
9
10
11
12
13
# 访问 state
默认情况下,你可以通过 store 实例访问 state,直接对其进行读写。
const store = useStore()
store.count++
2
# 四、Getter
Getter
完全等同于 store 的 state
的计算值。可以通过 defineStore()
中的 getters
属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数:
export const useStore = defineStore('main', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
})
2
3
4
5
6
7
8
大多数时候,getter
仅依赖 state
,不过,有时它们也可能会使用其他 getter
。 因此,即使在使用常规函数定义 getter 时,我们也可以通过 this
访问到 整个 store 实例。
export const useStore = defineStore('main', {
state: () => ({
count: 0,
}),
getters: {
// 自动推断出返回类型是一个 number
doubleCount(state) {
return state.count * 2
},
// 返回类型**必须**明确设置
doublePlusOne(): number {
// 整个 store 的 自动补全和类型标注 ✨
return this.doubleCount + 1
},
},
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
与计算属性一样,你也可以组合多个 getter
。通过 this
,你可以访问到其他任何 getter
。
export const useStore = defineStore('main', {
state: () => ({
count: 0,
}),
getters: {
// 类型是自动推断出来的,因为我们没有使用 `this`
doubleCount: (state) => state.count * 2,
doubleCountPlusOne() {
return this.doubleCount + 1
},
},
})
2
3
4
5
6
7
8
9
10
11
12
# 五、Action
Action 相当于组件中的 method
。它们可以通过 defineStore()
中的 actions
属性来定义,并且它们也是定义业务逻辑的完美选择。
export const useCounterStore = defineStore('main', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
2
3
4
5
6
7
8
9
10
11
12
13
类似 getter
,action
也可通过 this
访问 整个 store 实例,并支持完整的类型标注。不同的是,action
可以是异步的,你可以在它们里面 await
调用任何 API,以及其他 action
import { mande } from 'mande'
const api = mande('/api/users')
export const useUsers = defineStore('users', {
state: () => ({
userData: null,
// ...
}),
actions: {
async registerUser(login, password) {
try {
this.userData = await api.post({ login, password })
showTooltip(`Welcome back ${this.userData.name}!`)
} catch (error) {
showTooltip(error)
// 让表单组件显示错误
return error
}
},
},
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23