前端系列-8 集中式状态管理工具pinia

集中式状态管理工具—pinia

vue3中使用pinia作为集中式状态管理工具,替代vue2中的vuex。

pinia文档可参考: https://pinia.web3doc.top/introduction.html

1.项目集成pinia

安装pinia依赖:

npm install pinia

在main.ts中引入pinia

import { createApp } from 'vue'
import App from './App.vue'

// 从pinia库引入createPinia方法
import { createPinia } from 'pinia'

//调用createPinia方法创建pinia对象,设置到APP中
createApp(App).use(createPinia()).mount('#app')

2.定义store

pina提供了defineStore方法创建store,store作为集中式状态管理的实体,可被任意组件读取/写入数据。定义的store一般放在src/stores目录下。

import {defineStore} from 'pinia'

// 定义并暴露一个store
export const useXXXStore = defineStore('XXX', {
    // 配置信息
})

defineStore方法接收两个参数,store的唯一标识符和store的配置对象。其中,store配置对象中可以包含 state函数、actions对象、getters对象。
state中可以定义状态信息,getters基于state定义计算属性,actions中定义state相关的操作方法。以下结合案例进行说明:

// src/stores/clock.ts

import { defineStore } from 'pinia'

export const useClockStore = defineStore('clock', {
    state: () => {
        return { 
            hourHand: 0,
            minuteHand: 0,
            secondHand: 0
        }
    },

    getters:{
        time() {
            return this.hourHand +"时: "+this.minuteHand +"分: "+this.secondHand +"秒";
        }
    },

    actions: {
        increHour() {
            this.hourHand++;
        },
        getTime() {
            return this.time;
        }
    },
})

state中包含3个状态属性:hourHand和minuteHand和secondHand,初始值和默认值为0;
getters中定义了一个获取时间的方法time():根据状态值计算出时间信息;
actions中定义了一个修改状态变量的方法和一个获取计算属性的方法。

3.使用store

在任意组件中,可以引入和使用章节2中定义的store,方式如下:

import { useClockStore } from '@/stores/clock'
const clockStore = useClockStore()

得到clockStore这个store后,可以直接在template或者script脚本中通过属性名获取state的属性(含计算属性):

clockStore.time
clockStore.hourHand
clockStore.minuteHand
clockStore.secondHand

也可以调用store在actions中定义的方法:

clockStore.increHour()
clockStore.getTime()

使用章节2中定义的clock.ts完整的案例组件如下所示:

<template>
<div>
    <p>
        <span>{{clockStore.hourHand}}</span>
        <span>:</span>
        <span>{{clockStore.minuteHand}}</span>
        <span>:</span>
        <span>{{clockStore.secondHand}}</span>
    </p>
    <button @click="addHour">addHourBtn</button>
    <button @click="showTime">showTimeBtn</button>
    </div>
</template>

<script lang="ts" setup>
    import { useClockStore } from "@/stores/clock.ts";

    const clockStore = useClockStore();

    function addHour() {
        clockStore.increHour();
    }

    function showTime() {
        alert(clockStore.time);
    }
</script>

此时,clockStore中的状态属性和计算属性作为响应式数据。
除了上述通过store中actions定义的方法外,还可通过以下方式直接修改状态值:

clockStore.hourHand=12

// 批量修改
clockStore.$patch({
    hourHand:12,
    minuteHand:30,
    secondHand:0
})

4.响应式状态提取

章节3中提到过clockStore对象的状态属性和计算属性作为响应式数据,且可以直接操作clockStore对象的属性。
但是如果将其进行提取,则会失去响应式:

// clockStore.hourHand为响应式,修改为12后,页面会发生变化
clockStore.hourHand=12

// hour不是响应式对象
let hour = clockStore.hourHand

可以通过pinia的storeToRefs为其提供了一个解决方案:

import { storeToRefs } from 'pinia'

// 根据状态名称进行提取
const {hourHand, minuteHand,secondHand} = storeToRefs(clockStore)
hourHand.value = hourHand.value +100;

此时,可以在template结构中直接使用hourHand, minuteHand,secondHand,而不需要再使用clockStore.hourHand, clockStore.minuteHand,clockStore.secondHand.
解析出的数据为ObjectRefImpl类型,因此在script脚本中,修改和获取值时需要使用.value进行值的提取。

5.订阅store状态变化

可以通过store对象的$subscribe方法监听状态的变化,使用如下所示:

import { useClockStore } from "@/stores/clock.ts";
const clockStore = useClockStore();

clockStore.$subscribe((mutate, state)=>{
 // 定制操作
    console.log(mutate)
    console.log(state)
})

mutate中包含了发生变化的属性key以及变化前后的值;state为更新后的状态对象。
mutate参数打印信息如下:

{storeId: "clockStore", type: "direct", events:{key: "hourHand", oldValue: 0, newValue: 1}}

state参数打印信息如下:

Proxy {hourHand: 1, minuteHand: 0, secondHand: 0}
### Pinia 和 Vuex 的主要区别 #### 架构设计 Vuex 使用的是集中式架构,所有的应用状态都被存储在一个全局的状态树中。通过 `mutations` 进行同步状态更新,以及通过 `actions` 来处理异步逻辑[^5]。这种方式有助于保持状态的一致性和可预测性。 相比之下,Pinia 则采用了去中心化的架构,允许将状态分布到多个模块中。每个模块都可以独立定义自己的状态、`getters` 和 `actions`(不再区分同步和异步操作),从而提供更高的灵活性和更好的模块化能力。 #### API 设计与复杂度 Vuex 的 API 较为冗长,尤其是在 Vue 3 中使用时,开发者需要手动管理 `state`、`mutations`、`actions` 等逻辑[^1]。这增加了开发者的认知负担,并可能导致代码难以维护。 Pinia 基于 Vue 3 的 Composition API,其 API 更加简洁直观。它取消了 `mutations` 和 `actions` 的严格区分,使开发者能够以更自然的方式编写状态管理逻辑[^3]。因此,Pinia 的学习成本较低,适合快速上手的小型团队或个人开发者[^4]。 #### TypeScript 支持 在 TypeScript 支持方面,Pinia 明显优于 Vuex。由于 Pinia 是专门为 Vue 3 开发的状态管理库,它的设计充分考虑了现代 JavaScript 工具链的需求,提供了更强的类型推断能力和更友好的开发体验。 #### 社区支持与发展趋势 虽然 Vuex 拥有较长的历史积累和广泛的社区支持,但由于它是针对 Vue 2 及早期版本优化的设计,在 Vue 3 生态中的地位逐渐被 Pinia 所取代[^2]。随着越来越多的新项目迁移到 Vue 3,Pinia 成为了推荐使用的默认状态管理解决方案。 --- ```javascript // Vuex 示例代码 import { createStore } from 'vuex'; const store = createStore({ state() { return { count: 0, }; }, mutations: { increment(state) { state.count++; }, }, actions: { asyncIncrement({ commit }) { setTimeout(() => { commit('increment'); }, 1000); }, }, }); export default store; // Pinia 示例代码 import { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { state: () => ({ count: 0, }), actions: { increment() { this.count++; }, asyncIncrement() { setTimeout(() => { this.increment(); }, 1000); }, }, }); ``` --- ### 总结 总体而言,Pinia 提供了一种更为现代化、灵活且易用的状态管理模式,特别适用于基于 Vue 3 的中小型项目;而 Vuex 虽然功能强大,但在面对新一代框架特性时显得稍显笨重,更适合那些已经成熟的大规模应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值