Vue全新一代状态管理库 Pinia【一篇通】
文章目录
- 前言
- 1. Pinia 是什么?
- 1.1 为什么取名叫 Pinia?
- 1.2. 为什么要使用 Pinia ?
- 2. 安装 Pinia
- 2.1.创建 Store
- 2.1.1. Option 类型 Store
- 2.1.2 Setup 函数类型 Store
- 2.1.3 模板中使用
- 3. State 的使用事项(Option Store )
- 3.1 读取 State
- 3.2 重置 State
- 3.3 修改变更 State (批量修改)
- 4.getter 使用细节
- 4.1 getter 接收外部传进来的 参数
- 4.2 访问 其他 Store 仓库中的数据
- 5. action
- 总结
前言
Vue3 已经推出相当长一段时间了,同时其周边的生态支持,也越来越完善化了,如今Vue3 已经成为了官方的默认版本了,所以伴随着,目前处于一个生态集体过度的一个阶段,一些新的Api 支持也需要我们去了解学习,本章节文章,
带来的是 Vue 的全新一代 状态管理库 Pinia
,Pinia 已完美适配Vue3,并且 也获得Vue作者 尤雨溪,及Vue 官方推荐在Vue3中使用 Pinia 来实现状态管理,那么Pinia,究竟有什么厉害的地方?,本章节将为大家讲述 Pinia 的新特征!
1. Pinia 是什么?
如果你学习过 Vue2,那么你也就一定使用过 Vuex,想必大家也都知道,Vuex 在Vue2 中 充当的是集中式状态管理的角色,所谓集中式状态管理,就是把多个组件需要共享的的数据,整理到一个集中的地方进行托管,然后任何一个组件都能够从这里面读取到数据,它也是Vue 生态中的重要组成部分!,在 Vue3 中,你依然可以使用传统的 Vuex 来实现状态管理,但官方推荐在 Vue3 使用 Pinia 来做状态管理,你可以理解成 Pinia 就是 Vuex 的升级版!
Pinia 起始于 2019 年 11 月左右的一次实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库。
1.1 为什么取名叫 Pinia?
Pinia (发音为 /piːnjʌ/,类似英文中的 “peenya”) 是最接近有效包名 piña (西班牙语中的 pineapple,即“菠萝”) 的词。 菠萝花实际上是一组各自独立的花朵,它们结合在一起,由此形成一个多重的水果。 与 Store 类似,每一个都是独立诞生的,但最终它们都是相互联系的,
用来比喻 把一个一个的小格子数据,集中式管理在一起
,所以也有很多开发者,习惯性 的把 Pinia 称呼 为 “小菠萝”!
1.2. 为什么要使用 Pinia ?
很多小伙伴,看到这里也会表示疑惑,既然 Pinia 和 Vuex 的作用是 一样的,那么为什么 还需要 学习 Pinia ?它到底有什么 特别的有点吗?… 针对大家产生的疑惑,这也是正常的思考逻辑,毕竟 学习一件东西,也是需要一定成本的,如果,两者区别意义不大,那么确实是该思考,要不要学。那么我在这里告诉大家 Pinia ,非常值得去学习,他拥有很多 Vuex 不具备的优点,以及去除了很多冗余的部分!
优点
:
- Pinia 同时支持 Vue2 以及 Vue3 ,这让同时使用 两个版本的小伙伴更容易上手。
- Pinia 中 只存在了 State,getter,action,
剔除掉了 Vuex 中的 Mutation 以及 Module
。 - Pinia 中的 action 可以
同时支持同步任务和异步任务
。 - 更友好的支持了 TypeScript ,无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用
TS 类型推断
。 - Pinia在
修改状态的时候不需要通过其他api
,如:vuex需要通过commit,dispatch去修改,所以在语法上比vuex更容易理解和使用灵活。 - 由于去除掉了 Module ,无需再创建各个模块嵌套了,Vuex 中,如果数据过多,通常会通过划分模块来进行管理,而 Pinia 中,
每个 Store 都是独立的
,互不影响。 - 支持
服务端渲染
。 - …
注意事项:
想要学习 Pinia 最好要有 Vue3 的基础 ,明白组合式 Api 的概念,本篇文章的讲解是基于 Vue3 来使用的,虽然 Pinia 也能向下兼容 Vue2 ,但是却并不常用,在 Vue2 中 使用 Pinia 毕竟是少数!
点击学习 => Vue3 新特征 上手指南!
2. 安装 Pinia
在项目根目录下 使用命令安装
yarn add pinia# 或者使用 npmnpm install pinia
安装完成后 在 main.js 中,将 创建一个 pinia 实例 (根 store) 挂载到 应用实例身上。
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'const pinia = createPinia()
const app = createApp(App)app.use(pinia)
app.mount('#app')
官网 对 Store 的描述:
2.1.创建 Store
在 Pinia 中,Store 是使用 一个 defineStore() 函数 定义的,它的第一个参数要求是一个独一无二
的名字,这个名字 ,也被用作 id ,是必须传入的, Pinia 将用它来连接 store 和 devtools。为了养成习惯性的用法,将返回的函数命名为 use… 是一个符合组合式函数风格的约定。
import { defineStore } from 'pinia'// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useAlertsStore = defineStore('alerts', {// 其他配置...
})
defineStore() 的第二个参数可接受两种类型的值:Setup 函数或 Option 对象
2.1.1. Option 类型 Store
export const useAlertsStore = defineStore('counter', {state: () => ({ count: 17 }),getters: {double: (state) => state.count * 5,},actions: {increment() {this.count++ //这里的 this ,指向 state 所返回的 数据对象},},
})
你可以认为 state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods)。
2.1.2 Setup 函数类型 Store
import { ref , computed } from 'vue'
export const useCounterStore = defineStore('main', () => {let num = ref(4);let processnum = computed(() => {return num.value * 26})let Events = () => {num.value++}return { num, processnum, Events }
})
在 Setup Store 中:
- ref() 就是 state 属性
- computed() 就是 getters
- function() 就是 actions
注意
:所有 Store 在实例化之前,Store 仓库是不会被创建的!
2.1.3 模板中使用
<template><!-- Option Store 数据 方法 --><h1>{{ AlertsStore.count}}</h1><h1>{{ AlertsStore.double }}</h1><el-button type="primary" @click="addclcik">点击递增</el-button><!-- setup Store 数据方法 --><h1>{{ counterStore.num }}</h1><h1>{{ counterStore.processnum }}</h1><el-button type="primary" @click="counterStore.Events">点击递增</el-button>
</template><script>
import { useAlertsStore, useCounterStore } from '../../../Pinia/store'; // 导入 Store
export default {name: 'home',setup(props) {const AlertsStore = useAlertsStore(); //拿到 Option Store 实例const counterStore = useCounterStore(); // 拿到 setup Store 实例let addclcik= (() => {AlertsStore.increment()})return {AlertsStore,addclcik,counterStore}}
}
</script>
模板中对数据方法定义解构:
当有时候 Store 中的数据过多,嵌套多层,这时候在模板中,书写的 数据层级 会显得特别冗余,对此,我们首先想到的是对数据进行解构,由于 store 是一个用 reactive 包裹的对象,所以,我们如果直接对其解构,则会丢失响应式。
所以为了应对 丢失响应式 的问题, Pinia 官方 提供了一个 Api 函数 storeToRefs ()
注意:
: storeToRefs ()
只能 解构 状态数据 ,不能够解构 事件方法 !
<template><!-- Option Store 数据 方法 --><h1>{{ count }}</h1><h1>{{ double }}</h1><el-button type="primary" @click="addclcik">点击递增</el-button><!-- setup Store 数据方法 --><h1>{{ num }}</h1><h1>{{ processnum }}</h1><el-button type="primary" @click="Events">点击递增</el-button>
</template><script>
import { useAlertsStore, useCounterStore } from '../../../Pinia/store'; // 导入 Store
import { storeToRefs } from 'pinia'
export default {name: 'home',setup(props) {const AlertsStore = useAlertsStore(); //拿到 Option Store 实例const CounterStore = useCounterStore(); // 拿到 setup Store 实例// const { count, double } = AlertsStore; // 会丢失响应式// const { num, processnum } = CounterStore; // 会丢失响应式const { count, double } = storeToRefs(AlertsStore); // 不会丢失响应式const { num, processnum } = storeToRefs(CounterStore); // 不 会丢失响应式const { increment } = AlertsStore; const { Events } = CounterStore; let addclcik = (() => {increment()})return {count,double,increment,addclcik,num,processnum,Events}}
}
</script>
3. State 的使用事项(Option Store )
官方推荐在任何时候,state,都应该是一个函数的返回值,为了防止数据污染,这使得 Pinia 可以同时支持服务端和客户端。并且强力推荐 使用箭头函数,因为箭头函数 ,可以更好的适配TS 做类型 推理!
export const useStore = defineStore('counter', {state: () => ({count: 17,name: "张三"}),
})
3.1 读取 State
默认情况下,你可以通过 store 实例访问 state,直接对其进行读写。
const store = useStore()store.count++
const { count, name } = storeToRefs(store ); // 同时也能像上面提到的,采用解构 的方式读取
3.2 重置 State
可以通过调用 store 的 $reset() 方法将 state 重置为初始值。
const store = useStore()
store.$reset()
3.3 修改变更 State (批量修改)
除了用 store.count++ 直接改变 store,你还可以调用 $patch 方法。它允许你用一个 state 的补丁对象在同一时间更改多个属性:
store.$patch({count: store.count + 10,name: '张三丰',
})
// $patch 不会影响 ,源数据 中不需要修改的值, 底层做了 key 字段映射匹配,只会去修改,我传入的 key值
不过,用这种语法的话,有些变更真的很难实现或者很耗时:任何集合的修改(例如,向数组中添加、移除一个元素或是做 splice 操作)都需要你创建一个新的集合。因此,$patch 方法也接受一个函数来组合这种难以用补丁对象实现的变更。
store.$patch((state) => {state.count = 25state.name = "张三"
})
如果,业务逻辑相对比较复杂,也可以将 ,修改数据的方法,封装 在 Action 中
,使页面中减少冗余的代码。
4.getter 使用细节
定义 getter 方法函数
export const state = defineStore('counter', {state: () => ({count: 17,name: "张三"}),getters: {double(state) { //接收 一个参数 可以拿到 store 实例身上的 数据return state.count * 5return this.count * 5 //如果 这里没有传递参数,也可以通过 this,也能 访问到 store 实例 数据,这里的 this 指向 store 实例//注意, 使用 this 访问 store 这样的 写法,会影响 TS做 类型 推理。只能 手动 指定类型double: (state) => state.count * 5 //所以,官方建议推荐使用 箭头函数,可以更好的 配合 Ts 做类型推理}cases(state) { // 1275// 由于这里 可以 通过 this 访问 store 实例,所以在 当前 getter 里面 也可以访问 拿到其他 getter 的值。return this.double * 15}},
})
4.1 getter 接收外部传进来的 参数
export const useAlertsStore = defineStore('counter', {state: () => ({count: 17,name: "张三"}),getters: {double: (state) => (val) => { //返回 函数 接收 一个 外部传入参数return state.count * val},},
})
在模板中 调用 double 函数时 ,直接传入参数就行
注意
:请注意,当你这样做时,getter 将不再被缓存,它们只是一个被你调用的函数。
4.2 访问 其他 Store 仓库中的数据
export const useAlertsStore = defineStore('counter', {state: () => ({count: 17,name: "张三"}),getters: {double: (state) => (val) => {let CounterStore = useCounterStore(); //直接 可以 获取到 其他仓库的 实例。return state.count * CounterStore.processnum + val //1773},},
})export const useCounterStore = defineStore('main', () => {let num = ref(4);let processnum = computed(() => {return num.value * 26})let Events = () => {num.value++}return { num, processnum, Events }
})
5. action
action 中,既可以开启 同步任务,也可以 开启异步 任务,同时也能 访问 其他 Store 仓库 中的 方法数据。,方法和,上面 gtter 访问 其他 仓库 同理。,
export const useAlertsStore = defineStore('counter', {state: () => ({count: 17,name: "张三"}),getters: {double: (state) => (val) => {let CounterStore = useCounterStore();return state.count * CounterStore.processnum + val},},actions: {increment() { //actions 里面的 函数 只能通过 this 来访问数据 ,不能使用 箭头函数 ,只能定义普通函数。this.count++ //这里的 this ,指向 state 所返回的 数据对象//可以在这里开启异步任务},},
})
总结
以上就是本章节 所讲的 有关 Pinia 的内容,Pinia 作为 Vue3 生态圈中的新一代 状态管理库,后面肯定会成为 Vue 官方的主推生态。Pinia 还有更多的有趣点,大家可以去官网查看文档!
相关文章:

Vue全新一代状态管理库 Pinia【一篇通】
文章目录前言1. Pinia 是什么?1.1 为什么取名叫 Pinia?1.2. 为什么要使用 Pinia ?2. 安装 Pinia2.1.创建 Store2.1.1. Option 类型 Store2.1.2 Setup 函数类型 Store2.1.3 模板中使用3. State 的使用事项(Option Store )3.1 读取 State3.2 …...

STM32 -4 关于STM32的RAM、ROM
一 stm32 的flash是什么、有什么用、注意事项、如何查看 一 、说明 它主要用于存储代码,FLASH 存储器的内容在掉电后不会丢失,STM32 芯片在运行的时候,也能对自身的内部 FLASH 进行读写,因此,若内部 FLASH 存储了应用…...

第一个 Qt 程序
第一个 Qt 程序 “hello world ”的起源要追溯到 1972 年,贝尔实验室著名研究员 Brian Kernighan 在撰写 “B 语言教程与指导(Tutorial Introduction to the Language B)”时初次使用(程序),这是目前已 知最早的在计算机著作中将…...

Spring注解驱动开发--AOP底层原理
Spring注解驱动开发–AOP底层原理 21. AOP-AOP功能测试 AOP:【动态代理】 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式; 1、导入aop模块:Spring AOP,(Spring-aspects) 2、定义一个业务逻辑类(Ma…...

对象的动态创建和销毁以及对象的复制,赋值
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才…...

JVM调优,调的是什么?目的是什么?
文章目录前言一、jvm是如何运行代码的?二、jvm的内存模型1 整体内存模型结构图2 堆中的年代区域划分3 对象在内存模型中是如何流转的?4 什么是FULL GC,STW? 为什么会发生FULL GC?5 要调优,首先要知道有哪些垃圾收集器及哪些算法6 调优不是盲目的,要有依据,几款内…...

docker部署zabbix监控
docker部署zabbix监控 1、环境说明 公有云ubuntu22.04 系统->部署docker环境zabbix-server 6.4 2、准备docker环境 更新apt以及安装一些必要的系统工具 sudo apt-get update sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-co…...

C语言刷题(6)(猜名次)——“C”
各位CSDN的uu们你们好呀,今天,小雅兰还是在复习噢,今天来给大家介绍一个有意思的题目 题目名称: 猜名次 题目内容: 5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果: A选…...

两年外包生涯,感觉自己废了一半....
先说一下自己的情况。大专生,17年通过校招进入湖南某软件公司,干了接近2年的点点点,今年年上旬,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了五年的功能测试…...

【python】喜欢XJJ?这不得来一波大采集?
前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 俗话说的好:技能学了~就要用在自己喜欢得东西上!! 这我不得听个话~我喜欢小姐姐,跳舞的小姐姐 这不得用python把小姐姐舞采集下来~嘿嘿嘿 完整源码、素材皆可点击文章下方名片…...

公司测试员用例写得乱七八糟,测试总监制定了这份《测试用例编写规范》
统一测试用例编写的规范,为测试设计人员提供测试用例编写的指导,提高编写的测试用例的可读性,可执行性、合理性。为测试执行人员更好执行测试,提高测试效率,最终提高公司整个产品的质量。 一、范围 适用于集成测试用…...

LeetCode 热题 HOT 100【题型归类汇总,助力刷题】
介绍 对于算法题,按题型类别刷题才会更有成效,因此我这里在网上搜索并参考了下 “🔥 LeetCode 热题 HOT 100” 的题型归类,并在其基础上做了一定的完善,希望能够记录自己的刷题历程,有所收获!具…...

【Java进阶篇】—— File类与IO流
一、File类的使用 1.1 概述 File 类以及本章中的各种流都定义在 java.io 包下 一个File对象代表硬盘或网络中可能存在的一个文件或文件夹(文件目录) File 能新建、删除、重命名 文件和目录,但 File不能访问文件内容本身。如果我们想要访问…...

Mysql 竟然还有这么多不为人知的查询优化技巧,还不看看?
前言 Mysql 我随手造200W条数据,给你们讲讲分页优化 MySql 索引失效、回表解析 今天再聊聊一些我想分享的查询优化相关点。 正文 准备模拟数据。 首先是一张 test_orde 表: CREATE TABLE test_order (id INT(11) NOT NULL AUTO_INCREMENT,p_sn VARCHA…...

MATLAB算法实战应用案例精讲-【智能优化算法】海洋捕食者算法(MPA) (附MATLAB和python代码实现)
目录 前言 知识储备 Lvy 飞行 布朗运动 算法原理 算法思想 数学模型...

Spring @Profile
1. Overview In this tutorial, we’ll focus on introducing Profiles in Spring. Profiles are a core feature of the framework — allowing us to map our beans to different profiles — for example, dev, test, and prod. We can then activate different profiles…...

Vue3电商项目实战-个人中心模块4【09-订单管理-列表渲染、10-订单管理-条件查询】
文章目录09-订单管理-列表渲染10-订单管理-条件查询09-订单管理-列表渲染 目的:完成订单列表默认渲染。 大致步骤: 定义API接口函数抽取单条订单组件获取数据进行渲染 落的代码: 1.获取订单列表API借口 /*** 查询订单列表* param {Number…...

【十二天学java】day01-Java基础语法
day01 - Java基础语法 1. 人机交互 1.1 什么是cmd? 就是在windows操作系统中,利用命令行的方式去操作计算机。 我们可以利用cmd命令去操作计算机,比如:打开文件,打开文件夹,创建文件夹等。 1.2 如何打…...

【面试题】闭包是什么?this 到底指向谁?
一通百通,其实函数执行上下文、作用域链、闭包、this、箭头函数是相互关联的,他们的特性并不是孤立的,而是相通的。因为内部函数可以访问外层函数的变量,所以才有了闭包的现象。箭头函数内没有 this 和 arguments,所以…...

汽车4S店业务管理软件
一、产品简介 它主要提供给汽车4S商店,用于管理各种业务,如汽车销售、售后服务、配件、精品和保险。整个系统以客户为中心,以财务为基础,覆盖4S商店的每一个业务环节,不仅可以提高服务效率和客户满意度,…...

基于 pytorch 的手写 transformer + tokenizer
先放出 transformer 的整体结构图,以便复习,接下来就一个模块一个模块的实现它。 1. Embedding Embedding 部分主要由两部分组成,即 Input Embedding 和 Positional Encoding,位置编码记录了每一个词出现的位置。通过加入位置编码可以提高模型的准确率,因为同一个词出现在…...

算法小抄6-二分查找
二分查找,又名折半查找,其搜索过程如下: 从数组中间的元素开始,如果元素刚好是要查找的元素,则搜索过程结束如果搜索元素大于或小于中间元素,则排除掉不符合条件的那一半元素,在剩下的数组中进行查找由于每次需要排除掉一半不符合要求的元素,这需要数组是已经排好序的或者是有…...

大学四年..就混了毕业证的我,出社会深感无力..辞去工作,从头开始
时间如白驹过隙,一恍就到了2023年,今天最于我来说是一个值得纪念的日子,因为我收获了今年的第一个offer背景18年毕业,二本。大学四年,也就将就混了毕业证和学位证。毕业后,并未想过留在湖南,就回…...

C语言数据结构初阶(6)----链表常见OJ题
CSDN的uu们,大家好!编程能力的提高不仅需要学习新的知识,还需要大量的练习。所以,C语言数据结构初阶的第六讲邀请uu们一起来看看链表的常见oj题目。移除链表元素原题链接:203. 移除链表元素 - 力扣(Leetcod…...

关键字 const
目录 一、符号常量与常变量 二、const的用法 2.1 const常用方法 2.2 const用于指针 2.2.1 p指针所指的对象值不能改变,但是p指针的指向可以改变 2.2.2 常指针p的指向不能改变,但是所指的对象的值可以改变 2.2.3 p所指对象的指向以及对象的值都不可…...

MybatisPlus------MyBatisX插件:快速生成代码以及快速生成CRUD(十二)
MybatisPlus------MyBatisX插件(十二) MyBatisX插件是IDEA插件,如果想要使用它,那么首先需要在IDEA中进行安装。 安装插件 搜索"MyBatisX",点击Install,之后重启IDEA即可。 插件基本用途&…...

Leetcode138. 复制带随机指针的链表
复制带随机指针的链表 第一步 拷贝节点链接在原节点的后面 第二步拷贝原节点的random , 拷贝节点的 random 在原节点 random 的 next 第三步 将拷贝的节点尾插到一个新链表 ,并且将原链表恢复 从前往后遍历链表 ,将原链表的每个节点进行复制,并l链接到原…...

python并发编程多线程
在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合到一起,是一个…...

使用Maven实现Servlet程序
创建Maven项目我们打开idea的新建项目,选中里面Maven即可,如下图:创建完成之后,会看到这样的目录结构其中,main目录存放业务代码,其中的java目录存放的就是java代码,而resources目录存放是程序中依赖的文件,比如:图片,视频等.然后是 test目录,test目录存放的是测试代码.最后一个…...

百度的文心一言 ,没有想像中那么差
robin 的演示 我们用 robin 的演示例子来对比一下 文心一言和 ChatGPT 的真实表现(毕竟发布会上是录的)。 注意,我使用的 GPT 版本是 4.0 文学创作 1 三体的作者是哪里人? 文心一言: ChatGPT: 嗯&a…...