状态管理Pinia使用详解(带你入门)
状态管理Pinia使用详解(带你从入门到入神)
序:
如果你之前使用过 vuex 进行状态管理的话,那么 pinia 就是一个类似的插件。它是最新一代的轻量级状态管理插件。你可以通过defineStore来简单创建一个存储管理。
与 vuex 相比,pinia 提供了一个更简单的 API,具有更少的操作,提供了 Composition-API 风格的 API,最重要的是,在与 TypeScript 一起使用时具有可靠的类型推断支持。
特点:
- 完整的 ts 的支持;
- 足够轻量,压缩后的体积只有1kb左右;
- 去除 mutations,只有 state,getters,actions;
- actions 支持同步和异步;
- 代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
- 无需手动添加 store,store 一旦创建便会自动添加;
- 支持Vue3 和 Vue2
pinia官网
1.安装
yarn add pinianpm install pinia
2.引入注册Vue3
import { createApp } from 'vue'
import { createPinia } from 'pinia'import App from './App.vue'onst app = createApp(App)app.use(createPinia())app.mount('#app')
3.初始化仓库Store
3.1.新建一个文件夹Store
3.2.新建文件[name].ts
3.3.定义仓库Store
3.4.我们需要知道存储是使用定义的defineStore()
,并且它需要一个唯一的名称,作为第一个参数传递
新建文件store-namespace/index.ts
export const enum Names {Test = 'TEST'
}
store 引入
import { defineStore } from 'pinia'
import { Names } from './store-namespace'export const useTestStore = defineStore(Names.Test, {})
这个名称,也称为id,是必要的,Pania 使用它来将商店连接到 devtools。将返回的函数命名为*use…*是可组合项之间的约定,以使其使用习惯。
3.5.定义值
State 箭头函数 返回一个对象 在对象里面定义值
import { defineStore } from 'pinia'
import { Names } from './store-namespce'export const useTestStore = defineStore(Names.Test, {state:()=>{return {current:1}},//类似于computed 可以帮我们去修饰我们的值getters:{},//可以操作异步 和 同步提交stateactions:{}
})
4.State
4.1.State 是允许直接修改值的
例如current++
<template><div><button @click="Add">+</button><div>{{Test.current}}</div></div>
</template><script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {Test.current++
}</script><style></style>
4.2.批量修改State的值
<template><div><button @click="Add">+</button><div>{{Test.current}}</div><div>{{Test.age}}</div></div>
</template><script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {Test.$patch({current:200,age:300})
}</script><style></style>
4.3.批量修改函数形式
推荐使用函数形式 可以自定义修改逻辑
<template><div><button @click="Add">+</button><div>{{Test.current}}</div><div>{{Test.age}}</div></div>
</template><script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {Test.$patch((state)=>{state.current++;state.age = 40})
}</script><style></style>
4.4.通过原始对象修改整个实例
$state
您可以通过将store的属性设置为新对象来替换store的整个状态
缺点就是必须修改整个对象的所有属性
<template><div><button @click="Add">+</button><div>{{Test.current}}</div><div>{{Test.age}}</div></div>
</template><script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {Test.$state = {current:10,age:30}
}</script><style></style>
4.5.通过actions修改
定义Actions
在actions 中直接使用this就可以指到state里面的值
import { defineStore } from 'pinia';
import { store } from '@/store';export const useModalStore = defineStore({id: 'modal', // 唯一的idstate: () => ({modals: []}),actions: {add(modal) {this.modals.push(modal)},remove(id) {let index = this.modals.findIndex(v => v.id == id)if (index > -1) {this.modals.splice(index, 1);}}},
});// 在组件setup函数外使用
export function useModalStoreWithOut() {return useModalStore(store);
}
使用方法直接在实例调用
<script setup lang='ts'>
iimport { useModalStoreWithOut } from '@/store/modules/modal.store';const modalStore = useModalStoreWithOut();modalStore.remove({ id });
modalStore.add({ modal });</script><style></style>
5.解构store
在Pinia里,是不允许直接解构是会失去响应性的
const Test = useTestStore()const { current, name } = Testconsole.log(current, name);
差异对比
修改Test current 解构完之后的数据不会变
而源数据是会变的
<template><div>origin value {{Test.current}}</div><div>pinia:{{ current }}--{{ name }}change :<button @click="change">change</button></div>
</template><script setup lang='ts'>
import { useTestStore } from './store'const Test = useTestStore()const change = () => {Test.current++
}const { current, name } = Testconsole.log(current, name);</script><style>
</style>
解决方案可以使用 storeToRefs
import { storeToRefs } from 'pinia'const Test = useTestStore()const { current, name } = storeToRefs(Test)
其原理跟toRefs 一样的给里面的数据包裹一层toref
源码 通过toRaw使store变回原始数据防止重复代理
循环store 通过 isRef isReactive 判断 如果是响应式对象直接拷贝一份给refs 对象 将其原始对象包裹toRef 使其变为响应式对象
6.Actions,getters
6.1.Actions(支持同步异步)
6.1.1.同步可直接调用
import { defineStore } from 'pinia'
import { Names } from './store-naspace'
export const useTestStore = defineStore(Names.TEST, {state: () => ({counter: 0,}),actions: {increment() {this.counter++},randomizeCounter() {this.counter = Math.round(100 * Math.random())},},
})
<template><div><button @click="Add">+</button><div>{{Test.counter}}</div> </div>
</template><script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {Test.randomizeCounter()
}</script><style></style>
6.1.2.异步 可以结合async await 修饰
import { defineStore } from 'pinia'
import { Names } from './store-naspace'type Result = {name: stringisChu: boolean
}const Login = (): Promise<Result> => {return new Promise((resolve) => {setTimeout(() => {resolve({name: '小满',isChu: true})}, 3000)})
}export const useTestStore = defineStore(Names.TEST, {state: () => ({user: <Result>{},name: "123"}),actions: {async getLoginInfo() {const result = await Login()this.user = result;}},
})
<template><div><button @click="Add">test</button><div>{{Test.user}}</div> </div>
</template><script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {Test.getLoginInfo()
}</script><style></style>
6.1.3.多个action互相调用getLoginInfo setName
state: () => ({user: <Result>{},name: "default"}),actions: {async getLoginInfo() {const result = await Login()this.user = result;this.setName(result.name)},setName (name:string) {this.name = name;}},
6.2.getters
6.2.1.使用箭头函数不能使用this this指向已经改变指向undefined 修改值请用state
主要作用类似于computed 数据修饰并且有缓存
getters:{newPrice:(state)=> `$${state.user.price}`},
6.2.2.普通函数形式可以使用this
getters:{newCurrent ():number {return ++this.current}},
6.2.3.getters 互相调用
getters:{newCurrent ():number | string {return ++this.current + this.newName},newName ():string {return `$-${this.name}`}},
pinia插件
pinia和 vuex 都有一个通病 页面刷新状态会丢失
我们可以写一个pinia 插件缓存他的值
const __piniaKey = '__PINIAKEY__'
//定义兜底变量type Options = {key?:string
}
//定义入参类型//将数据存在本地
const setStorage = (key: string, value: any): void => {localStorage.setItem(key, JSON.stringify(value))}//存缓存中读取
const getStorage = (key: string) => {return (localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key) as string) : {})}//利用函数柯丽华接受用户入参
const piniaPlugin = (options: Options) => {//将函数返回给pinia 让pinia 调用 注入 context
return (context: PiniaPluginContext) => {const { store } = context;const data = getStorage(`${options?.key ?? __piniaKey}-${store.$id}`)store.$subscribe(() => {setStorage(`${options?.key ?? __piniaKey}-${store.$id}`, toRaw(store.$state));})//返回值覆盖pinia 原始值
return {...data}}}//初始化pinia
const pinia = createPinia()//注册pinia 插件
pinia.use(piniaPlugin({key: "pinia"}))
相关文章:
状态管理Pinia使用详解(带你入门)
状态管理Pinia使用详解(带你从入门到入神) 序: 如果你之前使用过 vuex 进行状态管理的话,那么 pinia 就是一个类似的插件。它是最新一代的轻量级状态管理插件。你可以通过defineStore来简单创建一个存储管理。 与 vuex 相比,pinia 提…...

Linux系统基础命令(一)
一、图形界面和终端界面 图形界面:是指采用图形方式显示的计算机操作用户界面。 终端界面:是指黑底白字的命令行界面。 什么是tty呢? tty:终端设备的统称。 tty一词源于Teletypes,或者teletypewriters,…...

djvu批量转换为pdf的工具和djvu阅读器(附下载链接)
简介 DjVuToy是一款美观易用、功能强大的DjVu处理工具,DjVuToy官方版功能包括图像文件转DjVu,支持PDG、BMP、GIF等格式。转换的同时可以进行OCR,生成双层DjVu。可以插入、删除、移动、旋转多页DjVu中的页面。还可以将多个DjVu文件合并成一个&…...

Linux | 分布式版本控制工具Git【版本管理 + 远程仓库克隆】
文章目录一、前言二、有关git的相关历史介绍三、Git版本管理1、感性理解 —— 大学生实验报告2、程序员与产品经理3、张三的CEO之路 —— 版本管理工具的诞生四、如何在Linux上使用Git1、创建仓库2、将仓库克隆到本地3、git三板斧① git add② git commit③ git push4、有关git…...

FFmpeg 编译和集成
背景FFmpeg 是一款知名的开源音视频处理软件,它提供了丰富而友好的接口支持开发者进行二次开发。FFmpeg 读作 “ef ef em peg” ,其中的 “FF” 指的是 “Fast Forward”,“mpeg” 则是 “Moving Picture Experts Group” (动态图…...

OOM的俩种情况---主动kill/被动kill
出现OOM, 有两种处理方式:1. 主动Kill; 2. 被动Kill 例:HBase Region Server OOM定位问题复盘 现象 在HBase资源隔离项目中,对测试集群进行压测时,发现region server会出现崩溃的情况,单机请求量从>200到~50每秒都…...
ssh远程连接ECS实例连接失败
尝试通过 SSH 远程连接服务来连接ECS云服务器实例时,收到“连接被拒”或“连接超时”的错误信息,可能的原因分析如下: 错误信息描述 1、错误消息:“ssh: connect to ecs-X-X-X-X.compute-xxxxxxxxx.com port 22: Connection tim…...
[框架设计] MVVM 的介绍,应用及优缺点
介绍 MVVM(Model-View-ViewModel)是一种架构模式,用于将应用程序分离为三个部分: Model(模型):负责处理应用程序的数据和业务逻辑。View(视图):负责呈现用户…...

4G模块DTU网关远程抄表方案(二):DL645/698协议国网电表
4G模块DTU网关远程抄表方案(二):DL645/698协议国网电表 1 DL 645协议简介 DL645协议是一种用于智能电能表的远程抄读通讯标准。制定该标准是为统一和规范多功能电能表与数据终端设备进行数据交换时的物理连接和通信链路及应用技术规范。DL645协议可用于远程监测电力传输和使用…...

认识微服务
目录 认识微服务 单体架构 分布式架构 服务架构演变 服务治理 微服务 总结 微服务技术对比 微服务结构 微服务技术对比 企业需求 SpringCloud SpringCloud和SpringBoot的版本兼容 认识微服务 单体架构 单体架构:将业务的所有功能集中在一个项目中开发&a…...

升级Android Studio Electric Eel问题汇总
1.升级以后找不到java可执行程序 问题原因:升级后,Android Studio自带的java目录不再是根目录/jre,调整为一个新目录 Studio根目录/jbr 修改方法:1)修改系统环境变量, JAVA_HOME调整为Studio下对应的java…...

令执法机构头疼的“虚拟货币犯罪”,为何链上天眼能“行”
谈到洗钱,你脑海中率先想到的可能是影视剧中利用赌场、收藏品拍卖等来实施犯罪。其实洗钱犯罪的花样不止于此,在近期热播的扫黑剧《狂飙》中,唐小龙为洗白“赌博资金、高利贷业务”,便通过“卖酒网销”的方式达成洗钱目的。 随着科…...

【unity】开发rts 3
一 出生点、阵营类型、阵营 实例栏-GameManage,默认有一个插槽 size 插槽数量 role 权限,host是主人,权限高 type 阵营类型,不选不限制,选的效果没看懂,文档原文: The Type field in Data al…...
突破老旧OA系统局限,打通五大业务管理体系,让效率“狂飙”
目录 用无代码构建上海致远信息化平台 一、支持类(行政人事、财务)体系 二、营销体系 三、供应链体系 四、质量管理体系 五、技术研发体系 下一步规划 我们公司用的第一套系统是 IBM 的系统,部署在本地服务器,这套系统用了十几年,当时 2020 年要全部迁移到LCHub低代…...

【vue2小知识】路由守卫的使用与解决RangeError: Maximum call stack size exceeded问题的报错。
🥳博 主:初映CY的前说(前端领域) 🌞个人信条:想要变成得到,中间还有做到! 🤘本文核心:当我们在路由跳转前与后我们可实现触发的操作 【前言】当我们在做类似于登录页面的时候&…...

Google Guice 5:AOP
1. AOP 1.1 实际开发中面临的问题 在实际开发中,经常需要打印一个方法的执行时间,以确定是否存在慢操作 最简单的方法,直接修改已有的方法,在finnally语句中打印耗时 Override public Optional<Table> getTable(String da…...

【同步、共享和内容协作软件】上海道宁与ownCloud让您的团队随时随地在任何设备上轻松处理数据
ownCloud是 一款开源文件同步、共享和 内容协作软件 可让团队随时随地 在任何设备上轻松处理数据 ownCloud开发并提供 用于内容协作的开源软件 使团队能够轻松地无缝 共享和处理文件 而无需考虑设备或位置 开发商介绍 ownCloud成立于2010年,是一个托管和同…...
Linux 文件、目录与磁盘格式
用户与用户组 用户:即某个文件的拥有者,可以管理自己账号下的文件,另有一个超级账号 root,可以统一管理全局,利用 su root 命令登录该账号。用户组:相当于群组,多个用户之间可以组成用户组&…...
锁屏面试题百日百刷-Hive篇(五)
锁屏面试题百日百刷,每个工作日坚持更新面试题。锁屏面试题app、小程序现已上线,官网地址:https://www.demosoftware.cn。已收录了每日更新的面试题的所有内容,还包含特色的解锁屏幕复习面试题、每日编程题目邮件推送等功能。让你…...

java多线程(七)线程等待与唤醒
一、wait()、notify()、notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用࿰…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...