Vue3中的pinia使用(收藏版)

news2024/12/25 12:53:46

1.pinia介绍

pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。就是和vuex一样的实现数据共享。
依据Pinia官方文档,Pinia是2019年由vue.js官方成员重新设计的新一代状态管理器,更替Vuex4成为Vuex5。
Pinia 目前也已经是 vue 官方正式的状态库。适用于 vue2 和 vue3。可以简单的理解成 Pinia 就是 Vuex5。也就是说, Vue3 项目,建议使用Pinia。

pinia官方文档

Pinia 的优点

  1. pinia 符合直觉,易于学习。
  2. pinia 是轻量级状态管理工具,大小只有1KB.
  3. pinia 模块化设计,方便拆分。
  4. pinia 没有 mutations,直接在 actions 中操作 state,通过 this.xxx 访问响应的状态,尽管可 以直接操作 state,但是还是推荐在 actions 中操作,保证状态不被意外的改变。
  5. store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或者是 MapAction 辅助函数,这是在 Vuex 中很常见的。
  6. 支持多个 store。
  7. 支持 Vue devtools、SSR、webpack 代码拆分。

更多查看文档…

2.pinia基本使用

  1. 首先先安装依赖
npm install pinia
  1. 在main.js中引入pinia并创建容器挂载到根实例上
//引入stores暴露出的pinia的实例
import pinia from './stores'

createApp(App).use(pinia).mount('#app')

  1. 创建stores文件夹和index.js文件(这个文件以后基本不用管了)
import { createPinia } from "pinia";

const pinia = createPinia()

export default pinia
  1. stores文件夹下创建counter.js文件。这个文件就是存有关counter相关的数据。(类似vuex的模块化)

defineStore 是需要传参数的,

  • 第一个参数是id,就是一个唯一的值,简单点说就可以理解成是一个命名空间.
  • 第二个参数就是一个对象,里面有三个模块需要处理,第一个是 state,第二个是 getters,第三个是 actions。
//定义关于counter的store
import {defineStore} from 'pinia'

/*defineStore 是需要传参数的,其中第一个参数是id,就是一个唯一的值,
简单点说就可以理解成是一个命名空间.
第二个参数就是一个对象,里面有三个模块需要处理,第一个是 state,
第二个是 getters,第三个是 actions。
*/
const useCounter = defineStore("counter",{
    state:() => ({
        count:66,
    }),
    
    getters: {

  	},

  	actions: {

  	}
})

//暴露这个useCounter模块
export default useCounter

注意:返回的函数统一使用useXXX作为命名方案,这是约定的规矩。例如上面的useCounter

  1. 然后再组件中使用:
<template>
	<!-- 在页面中直接使用就可以了 不用 .state-->
  <div>展示pinia的counter的count值:{{counterStore.count}}</div>

</template>

<script setup>
// 首先需要引入一下我们刚刚创建的store
import useCounter from '../stores/counter'
// 因为是个方法,所以我们得调用一下
const counterStore = useCounter()

</script>

注意:在模板使用 ,不用和vuex一样还要.state,直接点state里面的K

运行效果: 可以用vue3的调试工具看pinia

2.1注意Store获取到后不能解构,否则失去响应式

案例需求,点击按钮加一:
一个不解构,一个不解构看看区别。

<template>
  <div>展示pinia的counter的count值:{{counterStore.count}}</div>
  <div>展示解构出来的pinia的counter的count值:{{count}}</div>
  <button @click="addCount">count+1</button>
</template>

<script setup>
	import useCounter from '../stores/counter'
	
	const counterStore = useCounter()
	
	const {count} = counterStore
	
	function addCount(){
	  //这里可以直接操作count,这就是pinia好处,在vuex还要commit在mutaitions修改数据
	  counterStore.count++
	}
<script/>

在 vuex 里面是坚决不允许这样子直接操作 state 数据的,pinia是可以的,看看上面的addCount函数直接操作。

运行结果:

在这里插入图片描述
解决方案:
pinia提供了一个函数storeToRefs解决。引用官方API storeToRef 作用就是把结构的数据使用ref做代理

import {storeToRefs} from 'pinia'
const counterStore = useCounter()

const {count} = storeToRefs(counterStore)

现在数据都是响应式的了

在这里插入图片描述

3.修改state的数据

重新新建一个user模块
stores/user.js

//定义一个关于user的store
import {defineStore} from 'pinia'

const useUser = defineStore("user",{
    state:()=>({
        name:"紫陌",
        age:18
    })
})

export default useUser

组件中修改数据:
**第一种方法:**点击按钮修改数据,这种方法是最直接的修改数据

<template>
    <div>
        <h2>名字是:{{name}}</h2>
        <h2>年龄是:{{age}}</h2>
        <button @click="updateStore">修改Store数据</button>
    </div>


</template>

<script setup>
import useUser from '../stores/user'
import {storeToRefs} from 'pinia'

const userStore = useUser()

const {name,age} = storeToRefs(userStore)

function updateStore(){
    //一个个的修改状态
    userStore.name = "zimo"
    userStore.age = 20
}

效果:点击也修改了
在这里插入图片描述

第二种方法:$patch函数修改

function updateStore(){
    //一个个的修改状态
    // userStore.name = "zimo"
    // userStore.age = 20

    // 一次性修改多个状态
    userStore.$patch({
        name:"zimo",
        age:20
    })
}

这个方式也可以,效果一样。

第三种方法:$state 方式(这个是替换的方式。)这个基本不用,这里就不多说。可以看查阅文档。

第四种方法:$reset()函数是重置state数据的

新增一个重置按钮:

function resetStore(){
    userStore.$reset()
}

运行结果:点击了修改数据按钮之后在点重置按钮就恢复原始的数据。

在这里插入图片描述

4.getters的使用

getters 类似于 vue 里面的计算属性,可以对已有的数据进行修饰。不管调用多少次,getters中的函数只会执行一次,且都会缓存。

  1. 最基本的使用
    在counter模块演示了,counter模块:
//定义关于counter的store
import {defineStore} from 'pinia'

const useCounter = defineStore("counter",{
    state:() => ({
        count:66,
    }),

    getters:{
        //基本使用
        doubleCount(state) {
            return state.count * 2
        },
    },
})

//暴露这个useCounter模块
export default useCounter

组件中:

  <div>
        <h1>getters的使用</h1>
        <h2>doubleCount:{{counterStore.doubleCount}}</h2>
    </div>

运行效果:
在这里插入图片描述

这样就是最基本的使用了。

  1. 一个getter引入另外一个getter

couter模块:

getters:{
        //基本使用
        doubleCount(state) {
            return state.count * 2
        },
        //一个getter引入另外一个getter
        doubleCountAddTwo(){
            console.log(this);
            //this.是store实例
            return this.doubleCount + 2
        }
    },

组件中使用:

<div>
        <h1>getters的使用</h1>
        <h2>doubleCount:{{counterStore.doubleCount}}</h2>
        <h2>doubleCountAddTwo:{{counterStore.doubleCountAddTwo}}</h2>
    </div>

运行效果并且看看打印的this:

在这里插入图片描述

在这里插入图片描述

3.getters中用别的store中的数据

在counter模块中拿user模块的store数据。

count模块:

//定义关于counter的store
import {defineStore} from 'pinia'
import useUser from "./user"
const useCounter = defineStore("counter",{
    state:() => ({
        count:66,
    }),

    getters:{
        //基本使用
        doubleCount(state) {
            return state.count * 2
        },
        //一个getter引入另外一个getter
        doubleCountAddTwo(){
            console.log(this);
            //this.是store实例
            return this.doubleCount + 2
        },
        //getters中用别的store中的数据
        showMessage(state){
            console.log(state);
            console.log(this)
            //获取user信息,拿到useUser模块
            const userStore = useUser()
            //拼接信息
            return `name:${userStore.name}--count:${state.count}`
        }
    },
})

//暴露这个useCounter模块
export default useCounter

注意:要引入user模块

组件中:

 <div>
        <h1>getters的使用</h1>
        <h2>doubleCount:{{counterStore.doubleCount}}</h2>
        <h2>doubleCountAddTwo:{{counterStore.doubleCountAddTwo}}</h2>
        <h2>showMessage:{{counterStore.showMessage}}</h2>
    </div>

运行结果:
在这里插入图片描述

注意:我打印了this和store,他们都是当前这这个模块的实例

在这里插入图片描述
这样就在counter模块拿到了user模块的数据了。

5. actions的使用

actions 是可以处理同步,也可以处理异步,同步的话相对来说简单一点.actions类似methods

  1. 先看同步使用
    counter模块使用:
    在actions定义了两个函数一个加一的函数,一个加20的函数。
//定义关于counter的store
import {defineStore} from 'pinia'
const useCounter = defineStore("counter",{
    state:() => ({
        count:66,
    }),

    actions:{
        increment(state){
            //actions没有state,只能通过this拿store,这里打印
            console.log(state);
            this.count++
        },
        incrementNum(num){
            this.count += num
        }
    }
})

//暴露这个useCounter模块
export default useCounter

组件中:
actions函数在组件中使用

	<div>
        <h1>actions的使用</h1>
        <h2>count的事值:{{counterStore.count}}</h2>
        <button @click="changeState">count+1</button>
        <button @click="incrementNum">count+20</button>
      </div>

<script setup>
	import useCounter from '../stores/counter'
	const counterStore = useCounter()
	
	function changeState(){
	  counterStore.increment()
	}
	function incrementNum(){
	  counterStore.incrementNum(20)
	}
</script>

运行结果并且看看state是什么

初始值是66,点了一次加1和点了一次加20
在这里插入图片描述

注意:state的结果是undefined 所以actions只能通过this访问store。getter的话state和this都能访问。

在这里插入图片描述

  1. 异步操作使用

在 actions 处理异步的时候呢,我们一般是与 async 和 await 连用。
counter模块: 这里大致演示,具体还看自己怎么使用。

    state:() => ({
        count:66,
        list:[]
    }),
	actions:{
        //大概演示这个异步流程
        async axiosData(){
            const res = await fetch("http://-----------------")
            if(code ==200){
                //收到数据保存到store
                this.list = res.data.list
                return "ok"
            }
        }

    }

组件使用:

<template>
      <!-- 遍历store的数据 -->
      <div v-for="item in counterStore.list"></div>
</template>

<script setup>
import useCounter from '../stores/counter'
const counterStore = useCounter()

counterStore.axiosData().then(res =>{
  console.log("成功",res);
})
</script>

就这样可以啦!!!

是不是比vuex简洁很多。。。

6.数据的持久化

pinia支持扩展插件

我们想实现数据持久化

npm i pinia-plugin-persist

export const useUserStore = defineStore({
  state () {
    return {
      count: 0,
      num: 101,
      list: [1, 2, 3, 4 ]
    }
  },
  persist: {
    enabled: true, // 开启缓存  默认会存储在本地localstorage
    storage: sessionStorage, // 缓存使用方式
    paths:[] // 需要缓存键 
  }
})

效果:

在这里插入图片描述

文章有写的不当的地方,欢迎指正修改。如果感觉文章实用对你有帮助,欢迎点赞收藏和关注,你的点赞关注就是我动力,大家一起学习进步。

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

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

相关文章

原创 | 传统医药零售如何实现数字化转型

一、数字化转型是零售药店未来实现增长的必由之路“十四五”规划将清洁能源、军事、消费、医药以及高端制造等行业定为未来需要重点关注的领域。围绕“医保、医疗、医药”三条主线&#xff0c;医药行业推出了一系列重要的改革措施&#xff0c;即将进入有史以来最大变革的黄金时…

【Mysql 基础知识】

一、引言 #1.1 现有的数据存储方式有哪些&#xff1f; Java程序存储数据&#xff08;变量、对象、数组、集合&#xff09;&#xff0c;数据保存在内存中&#xff0c;属于瞬时状态存储。 文件&#xff08;File&#xff09;存储数据&#xff0c;保存在硬盘上&#xff0c;属于持久…

Talk | 香港大学在读博士生马逴凡:重新思考分辨率对于高效视频理解的意义

本期为TechBeat人工智能社区第460期线上Talk&#xff01; 北京时间12月7日(周三)20:00&#xff0c;香港大电子电机在读博士生——马逴凡的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “重新思考分辨率对于高效视频理解的意义 ”&#xff0c;届时…

web课程设计:HTML非遗文化网页设计题材【京剧文化】HTML+CSS+JavaScript

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

12.8 - 每日一题 - 408

每日一句&#xff1a;成功与不成功之间有时距离很短只要后者再向前几步。 数据结构 1 若用冒泡排序方法对序列&#xff08;12&#xff0c;24&#xff0c;36&#xff0c;48&#xff0c;60&#xff0c;72&#xff09;从大到小排序&#xff0c;需要的比较次数是_____ A. 5 B. 1…

Tableau制作三元相图/三角图(Ternary/Triangle Chart)

三元相图 三角图就是有三个轴的坐标图&#xff0c;可以分别表示一个点在X、Y、Z三个维度上的不同比例情况。 与传统的XY坐标轴不同。XY坐标轴是有两个维度&#xff0c;而且每个维度没有上下限的限制。三角图中每个维度都在0-1的范围内&#xff0c;按百分比划分&#xff0c;即…

图像处理算法实战应用案例精讲-【目标检测】YOLO

前言 物体检测——顾名思义就是通过深度学习算法检测图像或视频中的物体。目标检测的目的是识别和定位场景中所有已知的目标。有了这种识别和定位,目标检测可以用来计数场景中的目标,确定和跟踪它们的精确位置,同时精确地标记它们。 目标检测通常与图像识别相混淆,所以在…

easyExcel 数据导入

前言 这段时间做了excel 数据导入&#xff0c;用的阿里巴巴的easyExcel 的代码。下面是官网和githab 代码地址。需要将github 上的代码拉下来&#xff0c;方便查看demo.关于Easyexcel | Easy ExcelEasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目&#xff0c;在尽…

[附源码]Python计算机毕业设计SSM基于与协同过滤算法的竞赛项目管理(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

可重复读实现原理

浅解释 概念 1、InnoDB 在每行记录后面保存两个隐藏的列&#xff0c;分别保存了数据行的创建版本号和删除版本号。每开始一个新的事务&#xff0c;系统版本号都会递增。事务开始时刻的系统版本号会作为事务的版本号&#xff0c;用来和查询到的每行记录的创建版本号对比。 2、i…

RKMEDIA--VP使用

本章描述rkmedia vp模块 即视频一入四处功能的介绍。 使用场景&#xff1a;主要用在DVR/DMS产品上&#xff0c;需要多路视频节点的输入和获取。 可以rv1126/rv1109可以外接模拟高清RX芯片&#xff08;NVP6188,TP2815等&#xff09;&#xff0c;达到8路camera输入的能力。 在…

PLSQL导出、导入数据 和 同步数据 以及 navicat 里同步数据 以及解决plsql导出数据乱码问题

PLSQL导出、导入数据 和 同步数据 以及 navicat 里同步数据 以及解决plsql导出数据乱码问题1. 导出数据1.1 导出.pde文件1.2 导出sql文件1.2.1 导出sql压缩文件1.2.1 导出问题——乱码 与 解决乱码问题1. 尝试解决方式12. 尝试解决方式23. 直接换PLSQ版本&#xff08;最终解决问…

Traysoft AddTapi.NET 支持多条线路

Traysoft AddTapi.NET 支持多条线路 使用Traysoft AddTapi。您可以轻松地将手机功能添加到C#、VB.NET和C应用程序中。添加Tapi。NET将为您提供开发移动应用程序所需的一切。包括&#xff1a;电话呼叫、接收者ID、语音邮件、警告系统、电话呼叫跟踪和监控。添加Tapi。NET继续联系…

微服务框架 SpringCloud微服务架构 25 黑马旅游案例 25.3 我附近的酒店

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构25 黑马旅游案例25.3 我附近的酒店25.3.1 直接开干25 黑马旅游案例 25.3 …

计算机组成大题分析(四)

假设计算机 M 的主存地址为 24 位,按字节编址,采用分页存储管理方式,虚拟地址为 30 位,页大小为 4KB,TLB 采用 2 路组相联方式 和LRU 替换策略,一共8组。请回答一下问题。 (1) 虚拟地址中有哪几位表示虚页号? 哪几位表示内存地址? (2)己知访问 TLB 时虚页号高位部分用作 TLB…

留学Assignment写作语法错误怎么改正?

如何避免Assignment写作中的一些语法错误&#xff0c;在留学生提交论文要求进行润色修改时&#xff0c;经常会碰到一些语法上的错误&#xff0c;这都是英语水平的问题&#xff0c;同时也与自身的习惯相关&#xff0c;下面小编说一下Assignment写作的语法错误的几种情况&#xf…

浙江省AAA级“守合同重信用”公示企业

浙江省“守合同重信用”企业公示&#xff0c;是市场监管部门依企业自愿申请&#xff0c;对符合公示条件企业前两个年度内的合同履约信息向社会公示的行政指导行为。 浙江省“守合同重信用”企业公示实行逐级推荐、分级公示、动态管理制度。企业住所地县级市场监管局受理企业公示…

你还在使用swagger?试试这个吧

文章目录easyyapi插件使用1. 安装插件2. 配置插件3. 编写javadoc4. 上传接口javadoc5. 登录YApi,查看项目接口easyyapi插件使用 1. 安装插件 打开idea的Settings–>Plugins,查找easyyapi插件安装。 2. 配置插件 安装成功后&#xff0c;再次打开Settings–>OtherSett…

公司小程序小程序毕业设计,企业小程序系统设计与实现,微信小程序毕业设计论文怎么写毕设源码开题报告需求分析怎么做

项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于微信小程序公司企业站系统&#xff0c;前台用户使用小程序&#xff0c;后台管理使用基PHP开发&#xff0c;存储使用Mysql数据库&#xff1b;通过后台添加公司信息、资讯、产品等&#xff0c;用户通过小程…

vue+element+electron仿微信实现

一.仿得太像了有木有~ 1.登录窗口 2.主窗口 二.构思&#xff0c;以微信设计布局构思 以微信布局构思&#xff0c;参考element提供的组件&#xff1b;element提供的tabs标签页刚好能实现切换效果&#xff0c;element tabs 标签页&#xff1b;element tabs标签页虽然能达到切换…