Pinia 是 Vue.js 的轻量级状态管理库,易于学习和使用,具备模块化、可组合等特性。下面详细介绍 Pinia 的学习及使用配置。
Pinia 的基础概念
- Store: 它是 Pinia 的核心,用来保存应用的状态。可以把它想象成一个包含数据和方法的容器,这些数据和方法可在整个应用里共享。
- State: 这是存储在 Store 中的数据,类似于 Vue 组件里的 data。
- Getters: 其作用和 Vue 组件里的计算属性类似,可根据 State 派生出新的数据。
- Actions: 用于处理异步操作和修改 State,类似于 Vue 组件里的方法。
安装 Pinia
在项目中使用 Pinia,首先要进行安装,可以使用 npm 或者 yarn 来完成:
bash
# 使用 npm 安装
npm install pinia
# 使用 yarn 安装
yarn add pinia
在 Vue 项目中配置 Pinia
以下以 Vue 3 项目为例,介绍如何配置 Pinia:
-
创建 Pinia 实例
在项目里创建一个 store 目录,然后在该目录下创建 index.js 文件,用来创建 Pinia 实例:
javascript// store/index.js import { createPinia } from 'pinia'; const pinia = createPinia(); export default pinia;
-
在 Vue 应用中使用 Pinia
在项目的入口文件(通常是 main.js)中引入并使用 Pinia 实例:
javascript// main.js import { createApp } from 'vue'; import App from './App.vue'; import pinia from './store'; const app = createApp(App); app.use(pinia); app.mount('#app');
创建和使用 Store
-
创建 Store
在 store 目录下创建一个新的文件,例如 counter.js,用来定义一个简单的计数器 Store:
javascript// store/counter.js import { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { // 定义 state state: () => ({ count: 0 }), // 定义 getters getters: { doubleCount: (state) => state.count * 2 }, // 定义 actions actions: { increment() { this.count++; }, decrement() { this.count--; } } });
-
在组件中使用 Store
在 Vue 组件中引入并使用定义好的 Store:
javascript<template> <div> <p>Count: {{ counterStore.count }}</p> <p>Double Count: {{ counterStore.doubleCount }}</p> <button @click="counterStore.increment">Increment</button> <button @click="counterStore.decrement">Decrement</button> </div> </template> <script setup> import { useCounterStore } from '../store/counter'; const counterStore = useCounterStore(); </script>
进阶使用
-
模块化 Store
随着项目的扩大,可以把不同的业务逻辑拆分成多个 Store,这样能提高代码的可维护性。例如,创建一个 user.js 文件来管理用户相关的状态:
javascript// store/user.js import { defineStore } from 'pinia'; export const useUserStore = defineStore('user', { state: () => ({ userInfo: null }), actions: { setUserInfo(info) { this.userInfo = info; } } });
-
插件使用
Pinia 支持插件扩展功能,例如使用 pinia-plugin-persistedstate 插件来实现状态持久化:
bashnpm install pinia-plugin-persistedstate
javascript// store/index.js import { createPinia } from 'pinia'; import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; const pinia = createPinia(); pinia.use(piniaPluginPersistedstate); export default pinia;
在定义 Store 时,通过 persist 选项开启持久化:
javascript// store/counter.js import { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), actions: { increment() { this.count++; } }, persist: true });
Pinia 响应式原理实现
-
状态的响应式创建
当使用 defineStore 定义一个 Store 时,Pinia 会利用 Vue 3 的 reactive 函数将 state 函数返回的对象转换为响应式对象。以下是示例代码:
javascriptimport { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }) });
在这个例子中,state 函数返回的 { count: 0 } 对象会被 reactive 函数处理,从而变成一个响应式对象。这意味着当 count 属性的值发生变化时,Vue 3 的响应式系统会自动追踪到这个变化。
-
Getters 的响应式特性
Pinia 中的 getters 类似于 Vue 组件中的计算属性,它们是基于 state 派生出来的。getters 会自动追踪其依赖的 state 属性,当依赖的 state 属性发生变化时,getters 会重新计算并更新相关的组件。示例如下:
javascriptimport { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), getters: { doubleCount: (state) => state.count * 2 } });
在这个例子中,doubleCount 是一个 getter,它依赖于 state.count。当 state.count 发生变化时,doubleCount 会重新计算。
-
Actions 对状态的修改
actions 是用于修改 state 的方法,在 actions 中对 state 的修改会触发响应式更新。例如:
javascriptimport { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), actions: { increment() { this.count++; } } });
当调用 increment 方法时,this.count 的值会增加,由于 state 是响应式的,任何依赖于 count 的组件或 getters 都会自动更新。
依赖收集与触发更新流程
- 依赖收集: 当组件或 getters 访问 state 的属性时,Vue 3 的响应式系统会记录下这些依赖关系。例如,当组件渲染时读取 state.count,系统会将该组件与 state.count 建立依赖关系。
- 状态修改: 当在 actions 或其他地方修改 state 的属性时,Proxy 会拦截到这个修改操作。
- 触发更新: Proxy 检测到状态修改后,会通知所有依赖于该属性的组件和 getters 进行更新,从而实现界面的重新渲染或 getters 的重新计算。