Vue3状态管理库Pinia——核心概念(Store、State、Getter、Action)

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js 🍖JS版算法
🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

Pinia

内容参考链接
Vue3正式发布那么久了,你认识Pinia了吗?认识Pinia,搭建开发环境

文章目录

  • Pinia
    • ✨✨前言
    • ✨✨Store
      • 🎈🎈🎈State
      • 🎈🎈🎈Getters
      • 🎈🎈🎈Action
    • 🎉🎉本篇小结


✨✨前言

各位新朋友、老朋友们大家好,这里是前端杂货铺,欢迎各位的到来!!

上篇文章 我们初步认识了 Pinia,并进行了项目环境的搭建。接下来,我们从 Pinia 的核心模块着手,继续学习吧~

✨✨Store

store 就是 数据仓库,我们可以把它看成一个 只存放数据的公共组件。

🎈🎈🎈State

state 是 store 的核心,表示当前模块的状态,里面存放着我们需要使用的数据。

我们在 store 文件夹下新建 user.ts 文件,导入 defineStore(用于定义 Store)。一般 const 定义的常量都为 useXxxStore,其中 Xxx 是 defineStore 的第一个参数 xxx

之后我们在 state 中定义 age 属性。

.store/user.ts

import { defineStore } from "pinia";

/**
 * pinia 中使用 definStore 方法来定义 store
 * 第一个参数是应用程序中的 store 的唯一 id
 * 第二个参数是一个对象,store 的配置项,比如配置 store 内的数据
 */
export const useUserStore = defineStore('user', {
    // state 为 store 的核心,表示当前模块的状态
    // 为了完整类型推理,推荐使用箭头函数
    state: () => {
        return {
            age: 22
        }
    }
})

App.vue 组件中,我们导入刚才定义的 useUserStore,并定义 userStore 常量接收 useUserStore 定义模块的相关状态,之后就可以在模板中通过 userStore.xxx 的方式进行响应式获取了。

我们可以如下定义 add() 方法,使得 userStore.age += 1,在模板中的 <button></button> 中调用 add() 方法,便可以实现每点击一次按钮加一。

App.vue

<template>
  <div class="text">
    Hello pinia,I am {{ userStore.age }} years old.
  </div>
  <button @click="add">+1</button>
</template>

<script setup lang="ts">
import { useUserStore } from './store/user'

// 使用 useUserStore 并返回定义模块的相关状态以及方法
const userStore = useUserStore()

const add = () => {
  // userStore 模块里面的 state 是响应式数据
  userStore.age += 1
}

</script>

<style>
.text {
  background: orange;
}
</style>

在这里插入图片描述


🎈🎈🎈Getters

Getter 是 defineStore 参数配置项(State、Getter、Action)里面的一个属性。Getter 属性是一个对象,该对象里面是各种方法。我们可以把 Getter 看成 Vue 中的计算属性,它的作用就是返回一个新的结果。

注:与计算属性类似,Getter 也有缓存效果。(值会基于其响应式依赖被缓存。值仅会在其响应式依赖更新时才重新计算。)

在 defineStore 的第二个参数(对象)中,我们定义 getters,在里面我们可以定义一些计算方法:

  • 可以直接写箭头函数,把 state 中的值传进来,处理之后并返回
  • 可以在计算方法中调用其他计算方法,但这时要使用普通函数的写法,注:函数要加上类型限制,不然报错
  • 不同于 Vue 的计算属性,pinia 中的计算方法可以直接接收参数,注意参数写在 return 返回的函数 ()

.store/user.ts

import { defineStore } from "pinia";

/**
 * pinia 中使用 definStore 方法来定义 store
 * 第一个参数是应用程序中的 store 的唯一 id
 * 第二个参数是一个对象,store 的配置项,比如配置 store 内的数据
 */
export const useUserStore = defineStore('user', {
    // state 为 store 的核心
    state: () => {
        return {
            name: '前端杂货铺',
            age: 20
        }
    },
    getters: {
        /**
         * 箭头函数的写法,直接把 state 中的值传进来使用
         * @param state 
         * @returns 
         */
        doubleAge: (state) => state.age * 2,
        /**
         * 如果要在 Getter 中调用其他的计算属性方法,不能使用箭头函数
         * 注意:需要自己定义当前方法的返回值类型
         * @returns 
         */
        getNameAndAge():string {
            return this.name + " and " + this.doubleAge;
        },
        /**
         * 接收页面上传过来的参数,我们用年龄加上它并返回
         * @returns 
         */
        getAddAge() {
            return (num: number) => this.age + num;
        }
    },
})

我们通过 useUserStore() 创建 userStore 实例,就可以通过 X.x 的方式使用了。

下面的代码中,我们不仅仅练习了计算属性的多种用法,还使用了 ref 作对比。从页面显示的结果中我们可以发现,当点击 Getter +1 按钮时,和计算属性相关的数据会发生改变(前四个会变)。当点击 Ref +1 时,和计算属性相关的数据不会发生改变(仅最后一个会变),进一步说明了 Getter 的缓存性。

App.vue

<template>
  <div style="background: orange">
    ##state## Hello pinia,I am {{ userStore.age }} years old.
  </div>
  <div style="background: skyblue">
    ##getters箭头函数## Hello pinia,I am {{ userStore.doubleAge }} years old.
  </div>
  <div style="background: yellow">
    ##getters普通函数##,Hello pinia,I am {{ userStore.getNameAndAge }} years
    old.
  </div>
  <div style="background: yellowgreen">
    ##getters计算属性传递参数##,Hello pinia,I am
    {{ userStore.getAddAge(5) }} years old.
  </div>
  <button @click="add">##Getter## +1</button>
  <div style="background: pink">##ref响应数据##,num: {{ num }}</div>
  <button @click="numAdd">##Ref## +1</button>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { useUserStore } from "./store/user";

// 使用 useUserStore 并返回定义模块的相关状态以及方法
const userStore = useUserStore();

const add = () => {
  // userStore 模块里面的 state 是响应式数据
  userStore.age += 1;
};

// ref 响应式数据
const num = ref(1);
const numAdd = () => {
  num.value += 1;
};
</script>

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


🎈🎈🎈Action

前面提到的 State 和 Getter 属性都主要是 数据层面的,并没有具体的业务逻辑代码,它们两个就和我们组件代码中的 data 数据和 computed 计算属性一样。如果我们有 业务代码 的话,最好写在 Actions 中,该属性就和我们组件代码中的 methods 相似,用来放置一些处理业务逻辑的代码。

  • state 对应 data
  • getter 对应 computed
  • action 对应 method

actions 中,我们定义修改 name 的同步方法 saveName() 和 异步方法 savaName2(),用于在 App.vue 组件中使用。

./store/user.ts

import { defineStore } from "pinia";

// 异步方法,延迟 1s
const dely = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(100)
        }, 1000)
    })
}

/**
 * pinia 中使用 definStore 方法来定义 store
 * 第一个参数是应用程序中的 store 的唯一 id
 * 第二个参数是一个对象,store 的配置项,比如配置 store 内的数据
 */
export const useUserStore = defineStore('user', {
    // state 为 store 的核心
    state: () => {
        return {
            name: '前端杂货铺',
            age: 20
        }
    },
    /**
     * 当前模块的相关方法
     * 存放当前模块的相关业务逻辑函数
     */
    actions: {
        /**
         * 在 pinia 中,可以直接通过 actions 修改 state
         * pinia 的 actions 里面既可以是同步也可以是异步
         * @param name 
         */
        saveName(name: string) {
            this.name = name;
        },
        /**
         * 调用异步方法,延迟 1s 更新 name 的值
         * @param name 
         */
        async saveName2(name: string) {
            // 延迟 1s 更新
            await dely();
            this.name = name;
        },
    }
})

App.vue

updateName 调用 saveName() 同步方法,点击名字立即由 前端杂货铺 => 3号杂货铺
updateName2 调用 saveName2() 异步方法,点击名字延迟 1s 后由 前端杂货铺 => 5号杂货铺

<template>
  <div style="background: orange">
    Hello pinia,My name is {{ userStore.name }} .
  </div>
  <button @click="updateName">同步修改</button>
  <button @click="updateName2">异步修改</button>
</template>

<script setup lang="ts">
import { useUserStore } from "./store/user";

// 使用 useUserStore 并返回定义模块的相关状态以及方法
const userStore = useUserStore();

const updateName = () => {
  // 直接使用 userStore 调用 actions 里定义的方法
  userStore.saveName('3号杂货铺')
}

const updateName2 = () => {
  userStore.saveName2('5号杂货铺')
}
</script>

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


🎉🎉本篇小结

本篇文章介绍了 Pinia 的核心概念。

store 是我们的数据仓库,在这里存放的数据可以在任意组件中使用,我们只需要在组件中 import 导入进来再实例化就可以使用了。

statestore 的核心,在此存放我们需要的数据。state 类似于组件中的 data。

getter 等同于 storestate 的计算值,大多数情况下,getter 仅依赖于 state,不过它们也可能会使用其他 getter,当我们使用常规的函数定义 getter 时,可以通过 this 访问到整个 store 实例。getter 类似于组件中的 computed

不同于 stategetter 针对的数据层面,action 针对的是业务逻辑层面,在 actions 中我们可以定义同步的方法,也可以定义异步的方法。actions 相当于组件中的 methods


好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. Pinia 官方文档
  2. Pinia 教程 【作者:千锋教育】

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/42780.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iClient3D for CesiumWebGL入门之使用vscode以服务方式运行调试

作者&#xff1a;超图研究院技术支持中心-于丁 iClient3D for Cesium&WebGL入门之使用vscode以服务方式运行调试 相信大家第一次使用SuperMap iClient3D for Cesium或SuperMap iClient3D for WebGL的时候&#xff0c;都遇到过和我一样的事情&#xff1a; 在文件夹中直接打…

Android Studio 提示 Failed to initialize editor问题的解决

Android Studio 从2018的版本升级到2021年的版本后&#xff0c;无法预览xml。我查了很久&#xff0c;最后发现是Gradle的版本和工具不匹配&#xff0c;按照开发工具的提示&#xff0c;升级版本即可&#xff0c;我的是从3.2.1升级到了4.2.2

生产者消费者模型

生产者消费者模型 文章目录 生产者消费者模型概念原则优点 基于BlockingQueue的生产者消费者模型BlockingQueue模拟实现单生产者消费者模型基于计算任务和存储任务的生产者消费者模型 概念 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题生产者和消费者彼…

C++ 单例模式(介绍+实现)

文章目录 一. 设计模式二. 单例模式三. 饿汉模式四. 懒汉模式结束语 一. 设计模式 单例模式是一种设计模式 设计模式(Design Pattern)是一套被反复使用&#xff0c;多数人知晓的&#xff0c;经过分类的&#xff0c;代码设计经验的总结。 为什么要有设计模式 就像人类历史发展会…

python机器学习(三)特征预处理、鸢尾花案例--分类、线性回归、代价函数、梯度下降法、使用numpy、sklearn实现一元线性回归

K-近邻算法(K-Nearest Neighboor) 特征预处理 数据预处理的过程。数据存在不同的量纲、数据中存在离群值&#xff0c;需要稳定的转换数据&#xff0c;处理好的数据才能更好的去训练模型&#xff0c;减少误差的出现。 标准化 数据集的标准化对scikit-learn中实现的大多数机器…

遥感目标检测(3)-DAL(Dynamic Anchor Learning for Object Detection)

目录 一、概述 二、背景 三、建议 1、旋转RetinaNet 2、动态锚框分布 3、匹配敏感损失 四、实验 一、概述 由于选择正样本锚框进行回归&#xff0c;不一定能够定位真实的GT&#xff0c;而部分负样本回归甚至可以回归到真实的GT&#xff0c;说明相当多的负样本锚框有着准…

【自启动配置】Ubuntu 设置开机自启动脚本

Ubuntu 开机运行的脚本和当前操作系统运行的级别有关&#xff0c;OS 的运行级别大概分为七个 目录 1、查看 OS 运行级别 2、创建自启动脚本 3、添加软链接 1、查看 OS 运行级别 输入命令 runlevel 查看当前系统运行级别。当前系统的运行级别为 5 2、创建自启动脚本 在 /et…

ZooKeeper原理剖析

1.ZooKeeper简介 ZooKeeper是一个分布式、高可用性的协调服务。在大数据产品中主要提供两个功能&#xff1a; 帮助系统避免单点故障&#xff0c;建立可靠的应用程序。提供分布式协作服务和维护配置信息。 2.ZooKeeper结构 ZooKeeper集群中的节点分为三种角色&#xff1a;Le…

多线程(JavaEE初阶系列2)

目录 前言&#xff1a; 1.什么是线程 2.为什么要有线程 3.进程与线程的区别与联系 4.Java的线程和操作系统线程的关系 5.多线程编程示例 6.创建线程 6.1继承Thread类 6.2实现Runnable接口 6.3继承Thread&#xff0c;使用匿名内部类 6.4实现Runnable接口&#xff0c;使…

html2Canvas+JsPDF 导出pdf 无法显示网络图片

html2CanvasJsPDF 导出pdf 问题&#xff1a;类似于下面着这种网络图片使用img导出的时候是空白的 https://gimg3.baidu.com/search/srchttp%3A%2F%2Fpics4.baidu.com%2Ffeed%2F7e3e6709c93d70cf827fb2fda054500cb8a12bc9.jpeg%40f_auto%3Ftoken%3Dd97d3f0fd06e680e592584f8c7a2…

深度学习——LSTM解决分类问题

RNN基本介绍 概述 循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一种深度学习模型&#xff0c;主要用于处理序列数据&#xff0c;如文本、语音、时间序列等具有时序关系的数据。 核心思想 RNN的关键思想是引入了循环结构&#xff0c;允许…

分布式 - 消息队列Kafka:Kafka分区常见问题总结

文章目录 01. Kafka 的分区是什么&#xff1f;02. Kafka 为什么需要分区&#xff1f;03. Kafka 分区有什么作用&#xff1f;03. Kafka 为什么使用分区的概念而不是直接使用多个主题呢&#xff1f;04. Kafka 分区的数量有什么限制&#xff1f;05. Kafka 分区的副本有什么作用&am…

动态内存管理基础详解

目录 1、为什么存在动态内存分配 2、动态内存函数的介绍 2.1 malloc和free 功能&#xff1a; 参数和返回值&#xff1a; 注意事项&#xff1a; tip: 2.2 calloc 2.3 realloc函数 功能&#xff1a; 参数和返回值&#xff1a; realloc开辟空间的两种情况 realloc会顺…

Rust操作MySQL

查询 本部分是对 「Rust入门系列」Rust 中使用 MySQL[1]的学习与记录 经常使用的时间处理库&#xff1a; chrono 流式查询使用&#xff1a; query_iter 输出到Vec使用&#xff1a; query 映射到结构体使用&#xff1a; query_map 获取单条数据使用&#xff1a; query_first 命名…

Hadoop简介以及集群搭建详细过程

Hadoop简介以及集群搭建详细过程 hadoop集群简介hadoop部署模式Hadoop集群安装1.集群角色规划2.服务器基础环境准备3.上传安装包hadoop安装包目录结构5.编辑hadoop配置文件6.分发安装包7.配置hadoop环境变量8.NameNode format(格式化操作) hadoop集群启动关闭-手动逐个进程启停…

漏洞复现-yapi远程执行命令漏洞复现

目录 漏洞原理漏洞发现漏洞描述影响范围 yapi学习漏洞复现环境搭建exp 入侵检测与防御参考 漏洞原理 漏洞发现 查看issue2229 漏洞描述 网站开放注册功能时可随意注册&#xff0c;设置全局mock脚本可执行任意代码。 影响范围 Yapi < 1.9.2 yapi学习 YApi 是高效、易…

vue3前端分页,全选翻页状态保持

直接贴代码&#xff0c;代码中有注释 <template><div class"viewer-container" id"viewer-container"><!-- 表格 --><el-table:row-key"getRowKeys":data"data.tableDataCopy"style"width: 100%"ref&…

Spring详解(学习总结)

目录 一、Spring概述 &#xff08;一&#xff09;、Spring是什么&#xff1f; &#xff08;二&#xff09;、Spring框架发展历程 &#xff08;三&#xff09;、Spring框架的优势 &#xff08;四&#xff09;、Spring的体系结构 二、程序耦合与解耦合 &#xff08;一&…

消息队列——rabbitmq的不同工作模式

目录 Work queues 工作队列模式 Pub/Sub 订阅模式 Routing路由模式 Topics通配符模式 工作模式总结 Work queues 工作队列模式 C1和C2属于竞争关系&#xff0c;一个消息只有一个消费者可以取到。 代码部分只需要用两个消费者进程监听同一个队里即可。 两个消费者呈现竞争关…

【itext7】itext7操作PDF文档之添加段落文本内容、添加List列表、添加Image图片、添加Table表格

这篇文章&#xff0c;主要介绍itext7操作PDF文档之添加段落文本内容、添加List列表、添加Image图片、添加Table表格。 目录 一、itext7操作PDF内容 1.1、添加段落文本内容 1.2、添加列表内容 1.3、添加图片 1.4、添加表格 &#xff08;1&#xff09;列宽采用点单位&#…