Pinia是Vue.js应用程序的状态管理库。它提供了一种简单,轻量级的解决方案,用于在Vue应用程序中管理和维护状态。Pinia库的特点是易于使用和集成,可以使开发者在不牺牲性能的情况下更有效地处理和维护状态。pinia中有三个概念,分别是:state、getter、action,对应于Vue组件中的:data、computed、methods。
一、安装和配置:
- 安装:通过命令:npm install pinia@2.1.7 ,或者在创建vue项目的时候勾选使用Pinia。
- 配置:在main.js中,需要创建pinia对象,并与app对象进行绑定,示例代码如下:
1 2 3 4 5 6 7 8
| import { createApp } from 'vue' import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App) app.use(createPinia()) app.mount('#app')
|
二、基本使用
通常在src目录下创建一个stores文件夹,然后在里面按需创建js文件。假设要创建一个用于管理counter全局变量的库文件,那么可以创建counter.js文件,然后填入以下代码:
1 2 3 4 5 6 7 8 9 10
| import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => { const count = ref(0) function increment() { count.value++ }
return { count, increment } })
|
或者使用选项式API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', { state: () => { return { count: 0 } }, // 也可以这样定义 // state: () => ({ count: 0 }) actions: { increment() { this.count++ }, }, })
|
这样就定义好了一个count变量,以后在组件中可以通过以下三种方式修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script setup> import { useCounterStore } from '@/stores/counter' const counterStore = useCounterStore() // 1. 直接修改 counterStore.count++ // 2. 使用$patch批量修改 counterStore.$patch({ count: counterStore.count + 1 }) // 3. 使用action修改 counterStore.increment() </script> <template> <!-- 直接从 store 中访问 state --> <div>Current Count: {{ counter.count }}</div> </template>
|
以上三种修改方式的应用场景如下:
- 如果只要修改一个状态变量,并且不需要额外的操作,那么推荐使用第一种方法。
- 如果要一次性修改多个状态变量,那么推荐使用$patch方法,效率更高。
- 如果在修改状态变量的同时要做一些额外的操作,那么推荐第三种方法。
三、一个更真实的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import { defineStore } from 'pinia'
export const useTodos = defineStore('todos', { state: () => ({ /** @type {{ text: string, id: number, isFinished: boolean }[]} */ todos: [], /** @type {'all' | 'finished' | 'unfinished'} */ filter: 'all', // 类型将自动推断为 number nextId: 0, }), getters: { finishedTodos(state) { return state.todos.filter((todo) => todo.isFinished) }, unfinishedTodos(state) { return state.todos.filter((todo) => !todo.isFinished) }, /** * @returns {{ text: string, id: number, isFinished: boolean }[]} */ filteredTodos(state) { if (this.filter === 'finished') { // 调用其他带有自动补全的 getters ✨ return this.finishedTodos } else if (this.filter === 'unfinished') { return this.unfinishedTodos } return this.todos }, }, actions: { // 接受任何数量的参数,返回一个 Promise 或不返回 addTodo(text) { // 你可以直接变更该状态 this.todos.push({ text, id: this.nextId++, isFinished: false }) }, }, })
|