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

# 或者使用 npm

npm 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 = 25
  state.name = "张三"
})

如果,业务逻辑相对比较复杂,也可以将 ,修改数据的方法,封装 在 Action 中,使页面中减少冗余的代码。

4.getter 使用细节

定义 getter 方法函数

export const state = defineStore('counter', {
    state: () => ({
        count: 17,
        name: "张三"
    }),
    getters: {
        double(state) {  //接收 一个参数 可以拿到 store 实例身上的 数据
            return state.count * 5
            return 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 还有更多的有趣点,大家可以去官网查看文档!

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

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

相关文章

EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)

1、前言 (1)本文主要是通过24c02芯片来讲解I2C接口的EEPROM操作方法&#xff0c;包含底层时序和读写的代码&#xff1b; (2)大部分代码是EEPROM芯片通用的&#xff0c;但是其中关于某些时间的要求&#xff0c;是和具体芯片相关的&#xff0c;和主控芯片和外设芯片都有关系&…

一天吃透TCP面试八股文

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

vue模板语法

src目录文件说明&#xff1a; 1&#xff0c;数据绑定{{}} 数据绑定最常见的形式就是使用{{}}&#xff08;双花括号&#xff09;语法的文本插值 在template中使用{{}}文本插值语法中&#xff0c;设置一个变量&#xff0c;再在script中引入data函数&#xff0c;在return中进行数…

接口测试和性能测试有什么区别?我敢打赌你一定不知道

目录 一、什么是接口测试 二、接口测试原理 三、接口测试步骤 四、什么是性能测试 五、性能测试步骤 六、接口测试和性能测试的区别 一、什么是接口测试 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点…

2023最全Python+Selenium环境搭建教程-你绝对想不到有这么简单!

还有视频版本结合项目实战介绍&#xff0c;轻松学习&#xff01; PythonSelenium自动化测试环境搭建Web自动化测试全套教程_哔哩哔哩_bilibiliPythonSelenium自动化测试环境搭建Web自动化测试全套教程共计180条视频&#xff0c;包括&#xff1a;1、Web自动化测试需求和挑战、2…

深度学习-Tensorflow使用Keras进行模型训练

本文以FasionMNIST/加州房价数据集为例&#xff0c;介绍KerasAPI进行分类问题/回归问题模型训练的方法Tensorflow版本Tensorflow和keara都需要2.0及以上版本import tensorflow as tf from tensorflow import keras print(tf.__version__) print(keras.__version__)分类MLP构建数…

AI_Papers周刊:第六期

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 2023.03.13—2023.03.19 文摘词云 Top Papers Subjects: cs.CL 1.UPRISE: Universal Prompt Retrieval for Improving Zero-Shot Evaluation 标题&#xff1a;UPRISE&#xff1a;改进零样本评估…

要是早看到这篇文章,你起码少走3年弯路,20年老程序员的忠告

文章目录前言一、程序员的薪资是怎么样的&#xff1f;二、我现在的情况适合做程序员吗&#xff1f;三、大学期间到底应该学些什么&#xff1f;四、工作还是考研&#xff1f;五、总结前言 我是龙叔&#xff0c;一名工作了20多年的退休老程序员。 如果你在工作之前看到这篇文章…

【AI大比拼】文心一言 VS ChatGPT-4

摘要&#xff1a;本文将对比分析两款知名的 AI 对话引擎&#xff1a;文心一言和 OpenAI 的 ChatGPT&#xff0c;通过实际案例让大家对这两款对话引擎有更深入的了解&#xff0c;以便大家选择合适的 AI 对话引擎。 亲爱的 CSDN 朋友们&#xff0c;大家好&#xff01;近年来&…

libcurl库访问人工智能平台之人脸识别

一、前言上一篇文章我们调用libcurl库去访问了百度&#xff0c;访问的是http协议的百度云主页。那么现在我们要基于翔云人工智能平台来实现人脸识别&#xff0c;具体的操作大概就是我们在linux下调用libcurl库去访问翔云人工智能平台&#xff0c;然后实现我们想要的两张人脸图片…

FPGA纯verilog实现RIFFA的PCIE通信,提供工程源码和软件驱动

目录1、前言2、RIFFA简介RIFFA概述RIFFA架构RIFFA驱动3、vivado工程详解4、上板调试验证并演示5、福利&#xff1a;工程代码的获取1、前言 PCIE是目前速率很高的外部板卡与CPU通信的方案之一&#xff0c;广泛应用于电脑主板与外部板卡的通讯&#xff0c;PCIE协议极其复杂&…

【Linux】基本指令介绍

前言从今天开始&#xff0c;我们一起来学习Linux的相关知识&#xff0c;今天先来介绍怎么登录Linux&#xff0c;并且介绍一些Linux的基本指令。使用 XShell 远程登录 Linux很多同学的 Linux 启动进入图形化的桌面. 这个东西大家以后就可以忘记了. 以后的工作中 没有机会 使用图…

蓝桥杯刷题冲刺 | 倒计时21天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.迷宫1.迷宫 题目 链接&#xff1a; 迷宫 - 蓝桥云课 (lanqiao.cn) 本题为填空题&#xff0c;只…

Three.js——learn02

Three.js——learn02Three.js——learn02通过轨道控制器查看物体OrbitControls核心代码index2.htmlindex.cssindex2.jsresult添加辅助器1.坐标轴辅助器AxesHelper核心代码完整代码2.箭头辅助器ArrowHelper核心代码完整代码3.相机视锥体辅助器CameraHelper核心代码完整代码Three…

近期投简历、找日常实习的一些碎碎念(大二---测试岗)

嘿嘿嘿&#xff0c;我又回来了&#xff0c;相信不少兄弟已经发现我似乎已经断更了好久&#xff0c;哈哈&#xff0c;我是尝试去找实习&#xff0c;投简历面试去了。 先说一下背景。 目录 背景 求职进行中 简历 投递和沟通 收获和感受 背景 博主&#xff0c;大二软件工程…

Arthas工具的基本使用

介绍 Arthas 是Alibaba开源的Java诊断工具&#xff0c;深受开发者喜爱。在线排查问题&#xff0c;无需重启&#xff1b;动态跟踪Java代码&#xff1b;实时监控JVM状态。Arthas支持JDK 6&#xff0c;支持Linux/Mac/Windows&#xff0c;采用命令行交互模式&#xff0c;同时提供丰…

Python截图自动化工具

1、展示部分源码(写的比较乱&#xff0c;哈哈) 2、功能展示 1&#xff09;首页 2&#xff09;按钮截图(用于自动翻页) 3&#xff09;保存位置按钮(选择图片保存的位置) 4&#xff09;重复次数&#xff0c;就是要截取多少次 5&#xff09;定位截屏(截取的内容&#x…

[数据分析与可视化] Python绘制数据地图1-GeoPandas入门指北

本文主要介绍GeoPandas的基本使用方法&#xff0c;以绘制简单的地图。GeoPandas是一个Python开源项目&#xff0c;旨在提供丰富而简单的地理空间数据处理接口。GeoPandas扩展了Pandas的数据类型&#xff0c;并使用matplotlib进行绘图。GeoPandas官方仓库地址为&#xff1a;GeoP…

尚融宝06-ECMAScript基本介绍和使用

目录 一、ECMAScript 1、ECMA 2、ECMAScript 3、什么是 ECMA-262 4、ECMA-262 历史 5、ECMAScript 和 JavaScript 的关系 二、基本语法 1、let声明变量 2、const声明常量 3、解构赋值 4、模板字符串 5、声明对象简写 6、定义方法简写 7、参数的默认值 8、对象拓…

QT常用位置函数区别

目录1、引言2、实验代码3、位置函数3.1 x()3.2 y()3.3 frame()3.4 pos()3.5 geometry()3.6 width()3.7 height()3.8 rect()3.9 size()1、引言 QT有众多图形绘制函数&#xff0c;包括x()、y()、frame()、pos()、geometry()、width()、height()、rect()、size()&#xff0c;它们…