一、简介
Pinia 是一个由 Vue.js 核心成员 Luy 带头开发的 Vuex 替代品,它基于 Vue 3 composition API 构建,提供了一种更加简洁优雅的状态管理方案。
相比于 Vuex,Pinia在以下几个方面提供了显著的改进:
- 支持 TypeScript
- 数据响应式更新更加优化
- 使用 composition API 来进行状态管理编写
- 提供了插件机制,易于扩展
- 支持多个 store 实例创建
二、安装和基本使用
安装 Pinia:
npm install pinia
在 Vue 3 的应用中,使用 createApp() 方法来创建实例:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
上述代码中,我们使用 createPinia() 方法来创建一个名为 Pinia 的插件,同时将其安装到 Vue 3 实例上,然后通过 app.mount() 来挂载应用。
接下来,来看一下如何在组件内部使用 Pinia 插件。
首先,需要定义一个 store 实例。
import { defineStore } from 'pinia'
export const useCounterStore = defineStore({
id: 'counter',
state: () => ({
count: 0
}),
actions: {
increment() {
++this.count
}
}
})
上面代码中,我们使用 defineStore() 方法来定义一个名为 useCounterStore 的 store 实例,其中包含 state、mutations 和 actions 等属性。
在使用 defineStore() 方法时,需要传入一个配置对象,其中包含以下属性:
id
: String 类型,用来唯一标识此 store 实例。state
: Function 类型,用来返回此 store 实例的状态对象。actions
: Object 类型,包含多个用于更新状态的方法。mutations
: Object 类型,包含多个用于更新状态的方法。getters
: Object 类型,包含多个读取状态值的方法。actionsContext
: Object 类型,包含多个上下文相关的方法。mutationsContext
: Object 类型,包含多个上下文相关的方法。
接下来,通过 useStore() 方法来使用 store 实例:
import { useCounterStore } from './store'
export default {
setup() {
const store = useCounterStore()
const handleIncrement = () => {
store.increment()
}
return {
handleIncrement,
count: store.count
}
}
}
上面的代码中,我们使用 useCounterStore() 来获取 useCounterStore 这个 store 实例对象,并将其赋值给一个变量 store,接着通过调用 store 实例对象中的 increment 方法来更新 count 状态值的值。
三、插件机制
在需要对 Pinia 进行扩展或者自定义时,可以使用 Pinia 提供的 plugin 机制来实现,插件可以为 Store 实例添加更多的能力和特性,如:日志记录、数据持久化等。
下面是一个使用插件的示例:
import { createPinia } from 'pinia'
import { Storage } from '@ionic/storage'
const storage = new Storage()
const store = createPinia()
store.use((pinia) => {
pinia.$onAction(({ type, payload }, state) => {
console.log(`Action ${type} with payload`, payload, `updated with state`, state)
})
pinia.$onMutation(({ type, payload }) => {
console.log(`Mutation ${type} with payload`, payload)
})
pinia.$subscribe((mutation, state) => {
storage.set(mutation.type, state)
})
pinia.$restore(({ type }) => {
return storage.get(type)
})
})
上述代码中,我们使用 use() 方法来安装插件,然后在回调函数内部对 Store 实例添加了四个功能:
- 使用 $onAction 方法来监听 actions 的修改,并在控制台中输出相关信息。
- 使用 $onMutation 方法来监听 mutations 的修改,并在控制台中输出相关信息。
- 使用 $subscribe 方法来监听 state 的修改,并将修改后的数据进行持久化。
- 使用 $restore 方法来获取持久化的数据并还原到 store 实例中。
四、多个实例的创建
Pinia 提供多个 Store 实例的创建方式,可以根据不同的需要创建不同的实例。
下面是一个多个实例同时运行的示例:
// file: store.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore({
id: 'counter',
state: () => ({
count: 0
}),
actions: {
increment() {
++this.count
}
}
})
export const useTodoStore = defineStore({
id: 'todo',
state: () => ({
todos: []
}),
actions: {
add(todo) {
this.todos.push(todo)
}
}
})
上述代码中,我们分别定义了两个 store 实例 useCounterStore 和 useTodoStore。
// file: main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import { useCounterStore } from './store'
const app1 = createApp(App)
const app2 = createApp(App)
app1.use(createPinia())
app2.use(createPinia())
const store1 = useCounterStore()
const store2 = useCounterStore()
app1.config.globalProperties.$store = store1
app2.config.globalProperties.$store = store2
app1.mount('#app1')
app2.mount('#app2')
上述代码中,我们首先通过 createApp() 方法来创建两个不同的 Vue 3 实例 app1 和 app2,接着分别为两个实例都安装了 Pinia,并声明了两个不同的 useCounterStore 实例对象 store1 和 store2,最后将 store 实例存放到每个实例的全局属性中,最终通过 app1 和 app2 来分别将两个实例挂载到不同的元素上。
五、总结
通过上述的介绍,可以看出 Pinia 是一个功能强大的状态管理方案,它比 Vuex 更加简单、直观、灵活,是 Vue 3 开发中值得推荐的一款工具。
在使用 Pinia 时,需要注意以下几点:
- 需要安装插件才能够实现更多的功能;
- 支持 TypeScript,需要进行类型约束;
- 使用 composition API 编写状态管理逻辑;
- 支持多个 Store 实例的创建。