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

举报
愚公搬代码 发表于 2025/03/30 17:32:11 2025/03/30
【摘要】 标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度博客之星TOP2,2023年度博客之星TOP2,2022年华为云十佳博主,2023年华为云十佳博主,2024年华为云十佳...
标题 详情
作者简介 愚公搬代码
头衔 华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。
近期荣誉 2022年度博客之星TOP2,2023年度博客之星TOP2,2022年华为云十佳博主,2023年华为云十佳博主,2024年华为云十佳博主等。
博客内容 .NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
欢迎 👍点赞、✍评论、⭐收藏

🚀前言

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

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

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

🔎1.Pinia 中的 Store

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

// CounterState.js
const userInfoStore = defineStore('userInfo', (/* ... */));

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

// 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 对象,接口创建出引用实例,对其内部的状态数据和动作方法可以直接调用:

<!-- 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 方法来批量更新多个状态。例如:

<!-- 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 中状态数据的变化来实现某些业务逻辑,可以使用 $subscribe 方法来增加状态订阅,例如:

<!-- 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 参数包括的字段

字段名
type direct:直接访问。patch object:patch对象修改。patchfunction:patch 对象修改。patch function:patch 函数修改
storeId Store 的名字
payload $patch 方法所携带的数据

🔎3.Pinia 中的 Getters

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

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

// 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 进行订阅,我们能够监听方法的调用情况以及调用结果,这为状态管理的精细化控制提供了极大的便利。例如:

<!-- 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 出现异常回调的函数
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。