Pinia 实战指南:轻松驾驭前端状态管理

前言

本文讲解一下在前端开发中经常使用的一个状态管理工具Pinia

Pinia 是 Vue 的专属状态管理库,很值得我们深入去学习一下

Pinia是什么?

Pinia是专门为Vue.js应用程序设计的一个状态管理库

主要特点:

  1. 简单性: Pinia的设计目标是提高开发效率和用户体验,因此它更加简单和简洁。
  2. 模块化: Pinia允许你将应用程序的状态划分为独立的"stores",每个store都有自己的状态、actions和getters。这种模块化设计使得代码更加组织有序。
  3. 响应式: Pinia利用Vue.js内置的响应式系统,状态的变化会自动反映在UI上。
  4. TypeScript支持: Pinia对TypeScript有良好的支持,非常适合使用TypeScript的项目。
  5. 组合式API: Pinia被设计为与Vue.js的组合式API配合使用,提供了更灵活的状态管理方式。
  6. Devtools集成: Pinia与Vue.js Devtools扩展程序集成,提供了强大的调试体验。

普通父子通信

这里我们首先看看普通的父子之间的通信是怎么样的?

父传子

Child.vue

  • Child.vue组件接受一个名为 title 的 prop,它是一个字符串类型。
  • 如果父组件没有传递 title prop,则默认值为 "hello"
  • 在模板中直接渲染 title
<template><div>{{ title }}</div>
</template><script setup>
// 父传子
defineProps({//   title: String,title: {type: String,default: "hello",},
});
</script>

App.vue

  • 在App.vue组件中,引入了 Child 组件。
  • 定义了一个名为 title 的变量,并赋值为 "hello world"
  • <Child> 组件上,使用 :title="title"title 变量传递给 Child 组件的 title prop。
<template><Child :title="title"></Child>
</template><script setup>
import { ref } from "vue";
import Child from "./components/Child.vue";const title = "hello world";
</script>

实现效果:

image.png

image.png

子传父

Child.vue

  • Child.vue组件包含一个按钮,当点击按钮时会触发 submit 方法。
  • submit 方法中,使用 defineEmits 函数定义了一个名为 'onSub' 的自定义事件。
  • 通过 emit('onSub', success) 触发这个自定义事件,并传递一个名为 'success' 的数据。
<template><button @click="submit">提交</button>
</template><script setup>// 子传父
const success = "success-666";const emit = defineEmits(['onSub']);
const submit = () => {// 把submit方法传给父组件emit('onSub', success);}
</script>

App.vue

  • 在App.vue组件中,引入了 Child 组件。
  • 使用 @onSub="handle" 监听 Child 组件触发的 'onSub' 事件。
  • 'onSub' 事件被触发时,会执行 handle 函数,并将 Child 组件传递的数据 'success' 赋值给 res 变量。
  • 最后在模板中显示 res 的值
<template><Child @onSub="handle"></Child><h1>{{ res }}</h1>
</template><script setup>
import { ref } from "vue";
import Child from "./components/Child.vue";const res = ref("");
const handle = (e) => {res.value = e;
};
</script>

实现效果:

动画.gif

使用公共变量通信

接下来我们去使用公共变量去通信,其实这个就有一点像pinia的通信方式了,但是这不是pinia,所以还不是很优雅,不过同样能够去实现通信的效果

global.js

global.js 文件中定义了一个全局的 sum 变量,并通过 ref 函数将其包裹成一个响应式的引用

import { ref } from "vue";export const sum = ref(0);

App.vue

App.vue 中, AddCount 两个组件被引入和渲染

<template><Add /><Count />
</template><script setup>
import Add from "./components/Add.vue";
import Count from "./components/Count.vue";
</script>

Add.vue

Add.vue 中, sum 变量被直接从 @/global 中导入并使用。当点击按钮时, sum 的值会递增

<template><div><button @click="sum++">add{{ sum }}</button></div>
</template><script setup>
import { sum } from '@/global';
</script>

Count.vue

Count.vue 中, sum 变量也被从 ../global 中导入并用于渲染

<template><div><h2>{{ sum }}</h2></div>
</template><script setup>
import { sum } from '../global'
</script>

这种方式确实可以实现组件之间的数据共享,但存在以下一些问题:

  1. 全局污染: 在大型应用程序中,如果大量使用这种全局变量的方式,很容易造成命名冲突和代码维护困难。
  2. 缺乏可扩展性: 随着应用程序的增长,管理全局变量会变得越来越复杂。很难对状态进行模块化和分层管理。
  3. 缺乏工具支持: 全局变量不像 Pinia 那样提供丰富的开发工具支持,比如时间旅行调试、持久化、热更新等。
  4. 不适合 SSR: 全局变量在服务端渲染(SSR)场景下可能会出现问题,因为每个请求都会共享同一个全局状态。

Pinia 提供了一个更加结构化和可维护的状态管理解决方案,接下来我们就去使用pinia了

Pinia通信

首先我们需要去安装Pinia

npm i pinia

接下来创建Pinia

image.png

import { createPinia } from "pinia";const pinia = createPinia();
export default pinia;

引入store到vue项目之中去

import { createApp } from "vue";
import App from "./App3.vue";
import store from "./store";const app = createApp(App);app.use(store);app.mount("#app");

接下来我们就可以去使用Pinia了,创建user.js

image.png

import { defineStore } from "pinia";
export const useUserStore = defineStore({id: "user",// 数据源state: () => {return {userInfo: {name: "c",age: 18,},};},// 仓库里的方法actions: {// 修改数据changeUserInfo(info) {this.userInfo = info;},// 修改名字changeUserName(name) {this.userInfo.name = name;},// 修改年龄changeUserAge(age) {this.userInfo.age = age;},},// 仓库里的计算方法getters: {afterAge(state) {return state.userInfo.age + 10;},},
});
  1. 定义 Store:

    • 使用 defineStore 函数定义了一个名为 "user" 的 store。这个 store 就是用于管理用户相关的状态和逻辑。
  2. State:

    • state 函数返回一个对象,该对象表示 store 的初始状态。在这个例子中,初始状态包含一个 userInfo 对象,包含 nameage 属性。
  3. Actions:

    • actions 对象定义了三个方法:

      • changeUserInfo: 用于更新整个 userInfo 对象。
      • changeUserName: 用于更新 userInfo.name 属性。
      • changeUserAge: 用于更新 userInfo.age 属性。
    • 这些 action 方法可以在组件中调用,以改变 store 中的状态。

  4. Getters:

    • getters 对象定义了一个计算属性 afterAge,它会返回 userInfo.age 加 10 的结果。
    • 这个计算属性可以在组件中使用,就像使用组件的 computed 属性一样。

接下来我们就去使用它了

首先创建User.vue

image.png

  • 这个组件直接使用 useUserStore 获取 user store 的实例。

  • 通过 computed 属性和 storeToRefs 工具函数,我们可以直接访问 store 中的 nameuserInfo 属性,而不需要手动解构。

  • 在模板中,我们展示了 nameuserInfo.age 以及通过 getter 计算的 afterAge

<template><div>姓名{{ name }}</div><div>年龄{{ userInfo.age }}</div><div>十年后年龄{{ userStore.afterAge }}</div>
</template><script setup>
import { useUserStore } from "@/store/user";
import { computed } from "vue";
import { storeToRefs } from "pinia";const userStore = useUserStore();const name = computed(() => userStore.userInfo.name);
const { userInfo } = storeToRefs(userStore);
</script>

接下来我去创建UpdataUser.vue

image.png

  • 这个组件也使用了 useUserStore 获取 user store 实例。
  • changeNamechangeAge 方法中,我们调用了 store 的 changeUserNamechangeUserAge action 方法来更新状态。
  • 这里需要注意,不要直接修改 userStore.userInfo 对象,而是使用定义好的 action 方法。这样可以确保状态的更新是受控的,并且能够触发相关的副作用和订阅。
<template><div><button @click="changeName">修改名字</button><button @click="changeAge">修改名字</button></div>
</template><script setup>
import { useUserStore } from "@/store/user";const userStore = useUserStore();const changeName = () => {// userStore.userInfo.name = "cc";// 不要写这种代码userStore.changeUserName("cc");
};const changeAge = () => {userStore.changeUserAge(20);
};
</script>

App.vue

  • 这是一个简单的父组件,包含了 UserUpdataUser 两个子组件。
  • 在这个示例中,我们演示了如何在不同的组件中使用同一个 Pinia store。
<template><User /><UpdataUser/>
</template><script setup>
import User from "./components/User.vue";
import UpdataUser from './components/UpdataUser.vue'
</script>

实现效果:

动画.gif

但是目前实现的效果是不具备持久化的能力,也就是说如果我们刷新页面,数据就会回到最开始的值

动画.gif

Pinia 支持开启持久化功能

将 store 的状态保存在浏览器的本地存储或会话存储中,这样即使页面刷新或浏览器关闭,状态也不会丢失。

开启 Pinia 持久化功能的步骤如下:

  1. 安装 Pinia 持久化插件:
npm install pinia-plugin-persistedstate
  1. 在 Pinia store 中引入并启用 persistedstate 插件:
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
  1. 在 Pinia store 中添加 persist: true 选项,指定要持久化的状态:
persist: {// 持久化enabled: true,strategies: [// 持久化策略{paths: ["userInfo"], // 需要持久化的数据storage: localStorage, // 持久化存储的位置},],},

现在就成功开启了持久化功能

动画.gif

可以看到我们修改数据后会在localStorage里添加数据,并且刷新页面数据也不会复原

总结

这篇文章详细介绍了如何在 Vue 组件中使用 Pinia 状态管理库。

使用 Pinia 与不使用 Pinia 时的组件通信方式相比,组件之间的通信更加简单和清晰

不再需要通过事件总线或 prop 逐层传递数据,而是可以直接访问共享的状态

这种模式可以让你的应用程序更加模块化和可维护

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gen_circle_contour_xld 创建XLD轮廓对应于圆或圆弧。

gen_circle_contour_xld (Operator)创建XLD轮廓对应于圆或圆弧。 Signature 签名 gen_circle_contour_xld( : ContCircle : Row, Column, Radius, StartPhi, EndPhi, PointOrder, Resolution : ) Description 描述 Gen_circle_contour_xld创建一个或多个圆弧或闭合的圆。圆…

全志A527 T527 android13支持usb摄像头

1.前言 我们发现usb摄像头在A527 android13上面并不能正常使用,需要支持相关的摄像头。 2.系统节点查看 我们查看系统是否有相关的节点生成,发现/dev/video相关的节点已经生成了。并没有问题,拔插正常。 3.这里我们需要查看系统层是否支持相关的相机, 我们使用命令进行…

鹦鹉智能财税系统:代账公司的智能化升级之路

随着新公司法的颁布与实施&#xff0c;财税政策的不断更新&#xff0c;以及大数据、人工智能等新技术的广泛应用&#xff0c;企业老板对于财税合规&#xff0c;以及企业资金安全的需求日益增加。乐财业-鹦鹉智能财税系统从企业老板视角出发&#xff0c;在助力企业合规经营的前提…

电机控制杂谈——位置环到底该用什么调节器?

1.为什么位置环用P调节器尽可以实现无静差调节&#xff1f; 当时在学《运动控制》这门课程时&#xff0c;用的是陈伯时老师的教材。在介绍调节器的时候&#xff0c;教材中说到&#xff0c;P&#xff08;比例&#xff09;调节器会存在稳态误差&#xff0c;所以在转速环和电流环…

node使用express在服务器上创建接口,携带参数访问时返回参数

一、下载nodejs​​​​​​Node.js — 在任何地方运行 JavaScriptNode.js is a JavaScript runtime built on Chromes V8 JavaScript engine.https://nodejs.org/zh-cn 二、 安装Express 找一个文件夹&#xff0c;创建 mkdir myapp cd myapp三、初始化一个新的Node.js项目&…

OS Copilot:新手测评体验

文章目录 前言一、OS Copilot&#xff08;阿里云操作系统智能助手&#xff09;简介二、测评体验总结OS Copilot 产品体验评测OS Copilot 产品功能反馈 前言 本文简单分享一下自己使用OS Copilot测评体验。 一、OS Copilot&#xff08;阿里云操作系统智能助手&#xff09;简介 …

linux驱动应用开发就业前景如何 ?

Linux驱动应用开发的就业前景可以说是非常广阔和有吸引力的&#xff0c;特别是随着物联网&#xff08;IoT&#xff09;、嵌入式系统、云计算和大数据等技术的迅速发展。我收集归类了一份嵌入式学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的…

zerotier-one自建根服务器方法五

一、简介 前面几篇文章已经写完了自己建立服务器的方法&#xff0c;今天写一下我在使用过程中遇到的问题和解决方法。 二、准备工作 准备一个有公网IP的云主机。 要稳定性、安全性、不差钱的可以使用阿里、腾讯等大厂的云服务器。 本人穷屌丝一枚&#xff0c;所以我用的是免…

【中项第三版】系统集成项目管理工程师 | 第 4 章 信息系统架构③ | 4.6

前言 第4章对应的内容选择题和案例分析都会进行考查&#xff0c;这一章节属于技术相关的内容&#xff0c;学习要以教材为准。本章分值预计在4-5分。 目录 4.6 网络架构 4.6.1 基本原则 4.6.2 局域网架构 4.6.3 广域网架构 4.6.4 移动通信网架构 4.6.5 软件定义网络 4.6…

【C++ 】-vector:新时代动态数组的革新与未来

目录 1. vector的介绍及使用 1.1 vector的介绍 1.1.1 vector是什么 1.1.2 vector的存储机制 1.2 vector的使用 1.2.1 定义和构造函数 1.2.2 迭代器 1.2.3 容量相关操作 1.2.4 元素访问和修改 1.3 迭代器失效问题 2. vector深度剖析及模拟实现 2.1 std::vector的模拟…

js实现移动蒙版层

移动蒙版层 可在整个页面拖动方块&#xff0c;但方块不能超出页面 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

阿里巴巴开源自然语音交互框架;在抱抱脸上使用LivePortrait;58种提示技术的工具库

✨ 1: FunAudioLLM FunAudioLLM是一个为人类和大型语言模型&#xff08;LLMs&#xff09;之间自然语音交互打造的语音理解和生成基础框架。 FunAudioLLM 是阿里巴巴集团Tongyi SpeechTeam推出的用于增强人类与大语言模型&#xff08;LLM&#xff09;自然语音交互的框架。该框…

去中心化 RAG 先行者,KIP Protocol 如何保护数据所有权、激活 AI 资产

AI 时代&#xff0c;人人都应实现 KnowledgeFi 的梦想或许并不遥远&#xff0c;KIP Protocol 正在生动践行这一价值理念&#xff0c;带动去中心化数字产权的创建与盈利&#xff0c;面向 CryptoAI 的蓝海市场迈出创新探索的技术步伐&#xff0c;朝着 Web3 行业打造去中心化 AI 的…

前端面试题25(css常用的预处理器)

在前端开发领域&#xff0c;CSS预处理器在面试中经常被提及&#xff0c;其中最流行的三种预处理器是Sass、LESS和Stylus。下面分别介绍它们的特点和优势&#xff1a; 1. Sass&#xff08;Syntactically Awesome Style Sheets&#xff09; 优势&#xff1a; 变量&#xff1a;允…

RK3588开发笔记(四):基于定制的RK3588一体主板升级镜像

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140288662 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

【机器学习】使用决策树分类器预测汽车安全性的研究与分析

文章目录 一、决策树算法简介决策树的结构分类和回归树 (CART)决策树算法术语决策树算法直觉 二、属性选择度量信息增益熵 基尼指数计算分割基尼指数的步骤 三、决策树算法中的过度拟合避免过度拟合的方法 四、导入库和数据可视化探索性数据分析重命名列名查看数据集的总结信息…

python库(8):re库实现字符串处理

1 re库简介 Python 的re库是一个功能强大的正则表达式模块&#xff0c;它允许用户执行各种复杂的字符串匹配和处理任务。 以下是re库的主要功能&#xff1a; 搜索&#xff1a;re.search() 用于搜索字符串中第一次出现的模式。匹配&#xff1a;re.match() 从字符串的开始位置…

ggplot2绘图点的形状不够用怎么办?

群里有这么一个问题&#xff1a; 请问老师&#xff0c;fviz_pca_ind 做pca&#xff0c;当设置geom.ind “point”&#xff0c;group>6时&#xff0c;就不能显示第7&#xff0c;8组的点&#xff0c;应该如何处理&#xff08;在不设置为文本的情况下&#xff09;&#xff0c;…

该让医疗垂类大模型,走出“试题”了

图源&#xff1a;123rf “现阶段&#xff0c;许多医疗垂类大模型就是伪命题&#xff0c;推理能力不行。” 一位观望大模型已久的医疗从业者玄彬&#xff08;化名&#xff09;发出了极为尖锐的批评。 在他看来&#xff0c;目前人工智能是靠scaling law涌现的&#xff0c;模型性…

【前端】使用chrom浏览器Network,查看前后台数据传输请求

使用chrom浏览器Network查看前后台数据传输请求 写在最前面查看前后台数据传输请求① 首先&#xff0c;打开开发者工具&#xff08;F12&#xff09;打开控制台&#xff0c;切换到Network面板。Network面板右键界面copy ②清空请求log ctrle两次或者点击clear图标 案例展示&…