当前位置: 首页 > news >正文

vue3状态管理,pinia的使用

​​​​​​​状态管理

        我们知道组件与组件之间可以传递信息,那么我们就可以将一个信息作为组件的独立状态(例如,单个组件的颜色)或者共有状态(例如,多个组件是否显示)在组件之传递,这样的话我们希望这个信息在所有组件中共享,这样就可以监控所有组件的状态,但是一般的信息传递方式想要在所有组件传递一个信息会形成一个复杂的关系网,不利于管理且中间组件若产生异常,这个关系网就会断裂,整个网页的组件就会变的无法监控,

所以我们需要一个工具来管理所有组件的状态,他需要以下几点功能

1.能够注册一个全局状态(store),形成一个中间件,让所有组件都能访问到,

2.当这个全局状态被某一个组件影响改变时,它能够让其他组件更新这个状态,

3.将信息独立出来,不因为一个组件错误,产生全局错误

vuex和pinia

vuex和pinia都是vue的状态管理工具,它们的作用相同,用法几乎没有区别,但是pinia的结构更加简洁,同时对Ts的兼容性更强。

vuex和pinia的核心

vuexpinia
state --- 状态信息state --- 状态信息
getter --- 选择性的读取信息getter --- 选择性的读取信息
mutation --- 可以执行同步操作action --- 可以执行同步和异步操作
action --- 可以执行异步操作 返回一个mutation

vuex和pinia的关系

Pinia 起源于一次探索 Vuex 下一个迭代的实验,因此结合了 Vuex 5 核心团队讨论中的许多想法。最后,我们意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分功能,所以决定将其作为新的推荐方案来代替 Vuex。

这两个工具相似度很高,作用也一致,当你熟练掌握其中一个时,另一个也能够轻松使用,这里我们还是使用pinia作为项目的状态管理器

pinia的基本使用

手动引入pinia

新建一个vue项目

npm create vue@latest

输入完项目名称后一路回车即可,对于是否引入pinia的选项我们暂时不选则, 

 

这里我们在src的目录下新建一个文件夹store,并在store下新建一个index.js,然后删除components文件夹的原内容,并新建两个vue文件

安装pinia包

npm install pinia

安装完成后可以在package中看到,然后我们开始导入pinia

main.js:

import './assets/main.css'import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'createApp(App).use(createPinia()).mount('#app')

 导入完成后我们在index.js中配置pinia

index.js:

import {defineStore} from 'pinia'export const useStore = defineStore('counter', {state: () => {return {// 定义状态counter: 0}},// 定义计算属性getters: {// 定义计算属性getCounter: (state) => {return state.counter>=5?state.counter:"数据不足"}},// 定义操作actions: {// 定义操作addCounter() {this.counter++}}// 定义其他选项// ...
})

 注意 :第一个参数counter是返回store的一个标识,在一个项目中,我们可以新建多个store来表示多个状态,每个状态都有一个标识;第二个参数是一个对象,里面包含了state定义状态可以返回多个值(任意类型)表示状态,getter定义了一个属性运算的方法,可以用来过滤数据,只拿需要的数据(外部使用这个方法时不带括号),action定义了一个操作(可以 是异步操作,外部调用是要带括号);

然后我们再对App.vue,myComA.vue,myComB.vue引入store中间件

App.vue,

<script setup>
import myComA from './components/myComA.vue'
import myComB from './components/myComB.vue'
import { useStore } from './store/index.js'
const store = useStore()</script><template><p>{{ store.getCounter }}</p><button @click="store.addCounter()">counter = {{ store.counter }}</button><myComA/><myComB/>
</template>

myComA.vue,

<script setup>//组合式API
import { useStore } from '../store/index'
const store = useStore()</script><template><div>myComA</div><p>{{ store.counter }}</p>
</template>

myComB.vue

<script setup>//组合式API
import { useStore } from '../store/index'
const store = useStore()</script><template><div>myComB</div><p>{{ store.counter }}</p>
</template>

这里要注意import引入index文件的路径有所不同

完整这些后我们启动项目

npm run dev

        点击一次按钮,store的counter值就加一,当这个值大于等于5时,会在App.vue中显示出来,否则显示数据不足,App.vue,myComA.vue,myComB.vue  3个组件中均有显示,说明3个组件都访问到了数据,它们绑定了一个共同的信息,即便我们移除了myComB.vue其他组件也没有受到影响

这样我们就为每个组件都设置了一个状态,

系统引入pinia

掌握了手动引入pinia后,我们可以再新建一个项目查看以下系统的pinia

npm create vue@latest

我们可以看到它是有一个stores文件夹的,同时再main.js,counter.js,package.json中也是有对应的配置的

我们可以观察到,它的配置方式和我们手动配置的方式有所不同,

其实这个pinia的配置类似于setup函数的结构,有选择式风格和组合式风格,这里采用的是组合式风格,2者的效果是完全一致的,可以自行对比两种方法

我们可以引入之前项目中App.vue,myComA.vue,myComB.vue  3个组件(注意这里的方法和文件名称有所改变)再启动项目查看

app.vue:
<script setup>
import myComA from './components/myComA.vue'
import myComB from './components/myComB.vue'
import { useCounterStore } from './stores/counter.js'
const store =useCounterStore()</script><template><p>{{ store.doubleCount }}</p><button @click="store.increment()">counter = {{ store.count }}</button><myComA/><myComB/>
</template>myComA.vue:
<script setup>//组合式API
import { useCounterStore } from '../stores/counter.js'
const store = useCounterStore()</script><template><div>myComA</div><p>{{ store.count }}</p>
</template>myComB.vue:
<script setup>//组合式API
import { useCounterStore } from '../stores/counter.js'
const store = useCounterStore()</script><template><div>myComB</div><p>{{ store.count }}</p>
</template>
npm run dev

可以看到实现了状态共享,在实际应用中我们使用系统引入pinia后,可以自己手动的将pinia的相关文件调整成我们需要的结构

扩展:pinia数据持久化

登录状态的数据问题

        pinia的状态共享功能最常见的使用就是登录状态的共享,它可以保存当前页面的一个登录状态,这样当你在登录页面登录成功后,其他页面可以共享这个登录状态,在一个页面退出登录后,其他页面也能够共享,这样网页就能区分用户和游客了。

        但是,pinia是基于内存实现的,当你刷新页面后,pinia保存的可共享数据就会刷新,这样我们就需要重新登录,我们希望用户登录后登录状态应该由网络请求返回的token(一段有时间限制会过期的数据)保存,所以我们需要实现pinia的数据持久化,让页面刷新后仍可以保留登录状态,

实现数据持久化

        想在浏览器内存下一串数据不会因为刷新而清空,我们可以想到localStorage就有这个功能,

pinia提供了一个插件,基于localStorage实现了数据的缓存,这样页面刷新后,pinia会先从localStorage中读取数据(一般是token)验证用户的登录状态,这样就不用反复登录了

pinia-plugin-persistedstate

安装插件:快速开始 | pinia-plugin-persistedstate (prazdevs.github.io)

npm i pinia-plugin-persistedstate

安装完成后可以在package.json中查看 

 注册插件:

在main.js中注册引入

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import {piniaPluginPersistedstate} from 'pinia-plugin-persistedstate'const app = createApp(App)
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)app.use(pinia)
app.mount('#app')

在store下创建pinia对象的文件内启用插件

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', () => {const count = ref(0)const doubleCount = computed(() => count.value * 2)function increment() {count.value++}return { count, doubleCount, increment }},{persist: true,//开启路由缓存},
)

 App.vue

<script setup>
import  {useCounterStore} from '@/stores/counter'const {count,increment} = useCounterStore();
increment();//action方法,使用pinia的数据
console.log(count);
</script>
<template></template>
<style scoped></style>

这个counter存储的数据就会被保留在本地了

这样每次打开执行这个自增的 方法时会先从原来保存的数据执行,而不会因为刷新内存丢失掉数据,从0开始执行

总结

        pinia是一个状态管理工具,它可以保存一个状态(数据),和一些方法,提供给给全局的组件共享。简单来说,pinia可以设置全局的响应量和方法,所有组件都可以访问到这些响应量和方法,并产生对应的变化

相关文章:

  • JavaScript、Kotlin、Flutter可以开发鸿蒙APP吗?
  • HTTP --tcp和keep-alive
  • oracle linux7安装oracle11g0204
  • 强化学习(一) 基本概念和赌博机问题
  • 【量算分析工具-获取高程】GeoServer改造Springboot番外系列八
  • 应用案例|精密制造中使用复合机器人得到显著提升
  • MySQL表的增删改查初阶(上篇)
  • Kubernetes集群Pod控制器
  • 解析Java中1000个常用类:ProcessHandle.Info类,你学会了吗?
  • 执行shell脚本时为什么要写成./test.sh,而不是test.sh?
  • 数据结构--关键路径
  • MYSQL之主从复制
  • JDBC 学习笔记(一)基础篇 - JDBC 搭建的六大步骤
  • 创建模拟器
  • 有关RIPv2认证技术与网络安全综合实验
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • Create React App 使用
  • ECMAScript入门(七)--Module语法
  • go语言学习初探(一)
  • Terraform入门 - 3. 变更基础设施
  • 大快搜索数据爬虫技术实例安装教学篇
  • 关于 Cirru Editor 存储格式
  • 关于springcloud Gateway中的限流
  • 简析gRPC client 连接管理
  • 讲清楚之javascript作用域
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 前端攻城师
  • 前端技术周刊 2019-01-14:客户端存储
  • 深度解析利用ES6进行Promise封装总结
  • 深入 Nginx 之配置篇
  • 使用docker-compose进行多节点部署
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 我从编程教室毕业
  • 小程序01:wepy框架整合iview webapp UI
  • 一些关于Rust在2019年的思考
  • const的用法,特别是用在函数前面与后面的区别
  • ​渐进式Web应用PWA的未来
  • # C++之functional库用法整理
  • # SpringBoot 如何让指定的Bean先加载
  • # 数论-逆元
  • #Datawhale X 李宏毅苹果书 AI夏令营#3.13.2局部极小值与鞍点批量和动量
  • #每天一道面试题# 什么是MySQL的回表查询
  • ( 10 )MySQL中的外键
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (k8s)Kubernetes本地存储接入
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (十一)手动添加用户和文件的特殊权限
  • (学习日记)2024.02.29:UCOSIII第二节
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .Net Core中Quartz的使用方法
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .net FrameWork简介,数组,枚举
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET 读取 JSON格式的数据