前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【愚公系列】《循序渐进Vue.js 3.x前端开发实践》064-Pinia 中的一些核心概念

【愚公系列】《循序渐进Vue.js 3.x前端开发实践》064-Pinia 中的一些核心概念

作者头像
愚公搬代码
发布2025-06-02 18:07:34
发布2025-06-02 18:07:34
8100
代码可运行
举报
文章被收录于专栏:历史专栏历史专栏
运行总次数:0
代码可运行

🚀前言

在现代前端开发中,状态管理是确保应用程序高效、可维护的关键因素之一。随着 Vue.js 的普及,Pinia 作为其新一代状态管理库,逐渐成为开发者的热门选择。Pinia 的设计不仅简洁明了,还提供了强大的功能,旨在简化状态管理的复杂性。

本文将深入探讨 Pinia 中的一些核心概念,帮助你更好地理解这个框架的工作原理和优势。我们将围绕 Pinia 的基本结构、状态、 getters 和 actions 等关键组成部分进行详细解析。同时,我们还将通过实例演示如何在实际项目中应用这些概念,从而实现高效的状态管理和数据流动。

🚀一、Pinia 中的一些核心概念

🔎1.Pinia 中的 Store

使用 Pinia 的核心在于定义“状态仓库”Store。在定义 Store 时,我们可以对要使用的状态数据进行定义。Pinia 框架中提供了 defineStore 方法来生成 Store 实例。定义一个 Store 非常简单:

代码语言:javascript
代码运行次数:0
运行
复制
// CounterState.js
const userInfoStore = defineStore('userInfo', (/* ... */));

defineStore 方法有两个参数,第一个参数为 Store 的名称,它需要是唯一的,第二个参数为配置对象或 setup 方法。13.1 节中的示例代码采用了配置对象的方式定义 Store,后续我们将采用 setup 方法的方式来定义 Store,例如:

代码语言:javascript
代码运行次数:0
运行
复制
// counterState.js
import { ref } from 'vue';

export const userInfoStore = defineStore('userInfo', () => {
    // setup 方法的用法一致
    const name = ref("nick");
    const age = ref(15);

    function incrementAge() {
        age.value += 1;
    }

    return { name, age, incrementAge };
});

在使用时,只要引入此 Store 对象,接口创建出引用实例,对其内部的状态数据和动作方法可以直接调用:

代码语言:javascript
代码运行次数:0
运行
复制
<!-- HelloWorld.vue -->
<script setup>
import { userInfoStore } from '../CounterState';

const userInfo = userInfoStore();
</script>

<template>
    <h1 @click="userInfo.incrementAge">
        name: {{ userInfo.name }}, age: {{ userInfo.age }}
    </h1>
</template>

🔎2.Pinia 中的 State

State 指的是状态数据。在 Pinia 中,支持通过选项式 API 或组合式 API 来定义状态。如果选择使用选项式 API 进行定义,在配置对象中设置 state 选项即可。此选项是一个函数,其返回所需的状态数据。值得注意的是,使用选项式 API 返回的状态数据无须通过 ref 等方法包装,它默认具备响应式特性。而使用组合式 API 则更为直接,类似于编写 Vue 组件的过程,在 setup 方法中声明并返回所需的状态数据。

对于在 Store 中定义的状态,我们可以直接访问,包括读取和修改。但需注意,Pinia 不允许在 Store 使用过程中动态添加新的状态。所有需要的状态数据必须在定义 Store 时就明确指定。除直接访问状态数据进行修改外,还可以使用 $patch 方法来批量更新多个状态。例如:

代码语言:javascript
代码运行次数:0
运行
复制
<!-- HelloWorld.vue -->
<script setup>
import { userInfoStore } from '../CounterState';

const userInfo = userInfoStore();
</script>

<template>
    <h1 @click="userInfo.incrementAge">
        name: {{ userInfo.name }}, age: {{ userInfo.age }}
    </h1>
    <button @click="userInfo.$patch({ name: 'Jaki', age: 30 })">更改用户信息</button>
</template>

在上面的例子中,调用 patch 方法传入了一个对象,将要修改的状态数据在此对象中指定即可。 patch 方法支持通过一个函数来修改当前状态数据。如果需要订阅 Store 中状态数据的变化来实现某些业务逻辑,可以使用

代码语言:javascript
代码运行次数:0
运行
复制
<!-- HelloWorld.vue -->
<script setup>
import { userInfoStore } from '../CounterState';

const userInfo = userInfoStore();

userInfo.$subscribe((mutation, state) => {
    console.log(mutation); // 当前的状态
    console.log(state);
});
</script>

无论是直接访问还是使用 patch 方法产生的状态变更,都会执行 subscribe 注册的订阅回调,此回调中的 mutation 参数封装了当次变更的信息,包括的字段如表 13-1 所示。

表 13-1 mutation 参数包括的字段

patch 对象修改。patch function:

patch 函数修改storeIdStore 的名字payload$patch 方法所携带的数据

🔎3.Pinia 中的 Getters

与 Vue 组件中定义计算属性的方式类似,Pinia 中的 Store 也支持定义“计算状态”。在 Vue 中,计算属性通常体现为 Getter 方法,它让我们能够对数据进行处理后再使用。对于 Pinia 而言,提供的状态数据可能并不总是直接适用于页面渲染,例如某些数值数据在展示时可能需要添加单位。通常,这些计算过程是通用的,即需要被多个组件共享,若每个使用该状态数据的组件都重复实现相同的计算逻辑,则会显得冗余。Pinia 允许我们在定义 Store 时,为其添加特定的计算属性,即 Getter 方法,从而避免代码重复,提升维护性和效率。

以组合式 API 为例,使用 Vue 中的 computed 函数来定义“计算状态”,代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
// CounterState.js
import { ref, computed } from 'vue';

const userInfoStore = defineStore('userInfo', () => {
    const name = ref("nick");
    const age = ref(15);

    function incrementAge() {
        age.value += 1;
    }

    const ageString = computed(() => {
        return `${age.value}岁`;
    });

    return { name, age, incrementAge, ageString };
});

export { userInfoStore };

Store 中的计算状态的使用与正常状态数据完全一致。

🔎4.Pinia 中的 Actions

在 Pinia 中,另一个至关重要的概念是 Action。在 Store 中,我们可以定义一系列操作函数,这些函数通常封装了对状态数据的修改行为。这样做允许我们将复杂的状态变更逻辑集中在 Store 内部,从而提升程序的可扩展性和可维护性。Pinia 中的 Action 具备一项强大功能,即支持订阅。通过对 Store 中的 Action 进行订阅,我们能够监听方法的调用情况以及调用结果,这为状态管理的精细化控制提供了极大的便利。例如:

代码语言:javascript
代码运行次数:0
运行
复制
<!-- HelloWorld.vue -->
<script setup>
import { userInfoStore } from '../CounterState';

const userInfo = userInfoStore();

// 添加 Action 订阅
userInfo.$onAction((action) => {
    // 动作的名称
    console.log(action.name);
    // 当前 Store 实例
    console.log(action.store);
    // 方法执行的参数
    console.log(action.args);
    // 方法成功完整执行后的回调钩子
    let afterCallback = action.after;
    // 方法有异常抛出的回调钩子
    let errorCallback = action.onError;

    console.log("方法执行开始前..");

    // 注册完成的回调
    afterCallback(() => {
        console.log("方法执行完成");
    });

    // 注册异常回调
    errorCallback(() => {
        console.log("方法执行异常");
    });
});
</script>

<template>
    <h1 @click="userInfo.incrementAge">
        name: {{ userInfo.name }}, age: {{ userInfo.age }}, ageString: {{ userInfo.ageString }}
    </h1>
</template>

使用 $onAction 添加行为的订阅时,其注册的回调函数的 action 参数中包含如表 13-2 所示的数据。

表 13-2 action 参数中包含的数据

字段名

描述

name

当前所调用的 action 的名字

store

当前的 Store 实例对象

args

参数列表

after

一个用来注册 Action 成功执行回调的函数

onError

一个用来注册 Action 出现异常回调的函数

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🚀前言
  • 🚀一、Pinia 中的一些核心概念
    • 🔎1.Pinia 中的 Store
    • 🔎2.Pinia 中的 State
    • 🔎3.Pinia 中的 Getters
    • 🔎4.Pinia 中的 Actions
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档