Vue3(四):Pinia

news2025/2/7 22:38:00

一、Pinia介绍

Pinia是一个专门为Vue.js设计的状态管理库,它提供了一种简单和直观的方式来管理应用程序的状态。在使用Pinia时,可以轻松地创建定义状态的存储,然后将其与Vue组件绑定,使它们能够使用该状态。和上一个博客提到的Vuex相比,Pinia 更加简单易用,体积更小,同时具有更好的 TypeScript 支持和插件系统。

在Vue.js的官网中,我们可以看到Pinia目前已经取代Vuex,成为Vue生态系统的一部分。

Vue2中我们用的是vuex,在Vue3中我们用Pinia.下面是vuex和pinia对比:

mutations 不再存在。他们经常被认为是 非常 冗长。他们最初带来了 devtools 集成,但这不再是问题。
无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用 TS 类型推断。
不再需要注入、导入函数、调用函数、享受自动完成功能!
无需动态添加 Store,默认情况下它们都是动态的,您甚至都不会注意到。请注意,您仍然可以随时手动使用 Store 进行注册,但因为它是自动的,您无需担心。
不再有 modules 的嵌套结构。您仍然可以通过在另一个 Store 中导入和 使用 来隐式嵌套 Store,但 Pinia 通过设计提供平面结构,同时仍然支持 Store 之间的交叉组合方式。 您甚至可以拥有 Store 的循环依赖关系。
没有 命名空间模块。鉴于 Store 的扁平架构,“命名空间” Store 是其定义方式所固有的,您可以说所有 Store 都是命名空间的。

接下来我们准备实现这样一个效果:

二、搭建Pinia 环境

1.通过以下方式安装:

(建议先去看一下字节vue版本,如果是vue3.3以上的可以直接安装2.1版本(默认最新版本)的pinia,如果不是请安装更低版本,否则项目运行时将报错) 

npm install pinia@2.0.36

2.引入并创建使用pinia

//main.ts
import { createApp } from 'vue';
import App from './App.vue';

/* 引入createPinia,用于创建pinia */
import { createPinia } from 'pinia';

/* 创建pinia */
const pinia = createPinia();
const app = createApp(App);

/* 使用插件 */ {
}
app.use(pinia);
app.mount('#app');

三、准备项目效果前期 

App.vue

<template>
    <Count />
    <br>
    <LoveTalk />
</template>

<script setup lang="ts" name="App">
import Count from './components/Count.vue'
import LoveTalk from './components/LoveTalk.vue'
</script>

components/Count.vue

<template>
    <div class="count">
        <h2>当前求和为:{{ sum }}</h2>
        <select v-model.number="n">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button @click="add">加</button>
        <button @click="minus">减</button>
    </div>
</template>

<script setup lang="ts" name="Count">
import { ref } from "vue";
// 数据
let sum = ref(1) // 当前求和
let n = ref(1) // 用户选择的数字

// 方法
function add() {
    sum.value += n.value
}
function minus() {
    sum.value -= n.value
}
</script>

<style scoped>
.count {
    background-color: skyblue;
    padding: 10px;
    border-radius: 10px;
    box-shadow: 0 0 10px;
}

select,
button {
    margin: 0 5px;
    height: 25px;
}
</style>

components/LoveTalk.vue

(这里涉及到一个nanoid库的使用,直接npm i nanoid即可,主要用于生成唯一id)

<template>
    <div class="talk">
        <button @click="getLoveTalk">获取一句土味情话</button>
        <ul>
            <li v-for="talk in talkList" :key="talk.id">{{ talk.title }}</li>
        </ul>
    </div>
</template>

<script setup lang="ts" name="LoveTalk">
import { reactive } from 'vue'
import axios from "axios";
import { nanoid } from 'nanoid'
// 数据
let talkList = reactive([
    { id: 'ftrfasdf01', title: '今天你有点怪,哪里怪?怪好看的!' },
    { id: 'ftrfasdf02', title: '草莓、蓝莓、蔓越莓,今天想我了没?' },
    { id: 'ftrfasdf03', title: '心里给你留了一块地,我的死心塌地' }
])
// 方法
async function getLoveTalk() {
    // 发请求,下面这行的写法是:连续解构赋值+重命名
    let { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
    // 把请求回来的字符串,包装成一个对象
    let obj = { id: nanoid(), title }
    // 放到数组中
    talkList.unshift(obj)
}
</script>

<style scoped>
.talk {
    background-color: orange;
    padding: 10px;
    border-radius: 10px;
    box-shadow: 0 0 10px;
}
</style>

这样我们可以看到初期效果 

 

 四、store和state/存储+读取数据

在src文件夹下新建store文件夹,在store文件夹下新建count.ts和loveTalk.ts。

1.store

Store是 Pinia 中管理状态的核心概念。它相当于一个 Vue 组件中的状态,但是 Store是一个独立的模块。

Store 是用 defineStore() 定义的,它的第一个参数要求是一个独一无二的名字,这个名字 ,也被用作 id ,是必须传入的, Pinia 将用它来连接 store 和 devtools。为了养成习惯性的用法,将返回的函数命名为 use… 是一个符合组合式函数风格的约定。

以useCountStore为例创建一个store:

// 引入defineStore用于创建store
import { defineStore } from 'pinia';

// 定义并暴露一个store
export const useCountStore = defineStore('count', {
...
})

2.State

State 是 store 中存储数据的地方。可以把之前存储在vue文件中的数据拿过来存储在state里面。通过定义 State,可以在 store 的任何位置访问和修改数据。

在 Pinia 中,state 被定义为一个返回初始状态的函数。这使得 Pinia 可以同时支持服务端和客户端。

用法:

count.ts和Count.vue中

同理,loveTalk.ts和LoveTalk.vue中

截至到这里就完成了存储和读取数据,但是还没有完成修改的功能,点击按钮是无效的。 

五、修改数据的三种方法

第一种:countStore.

以Count.vue为例,修改sum为例 

function add() {
    // 第一种修改数据的方法
    countStore.sum += 1
}

第一种修改方式就是修改几次mutation几次 

第二种:$patch

通过$patch 批量修改

<h2>当前求和为:{{ countStore.sum }}</h2>
  <h2>学校名称是{{ countStore.school }},坐落于{{ countStore.address }}</h2>
 
function add() {

    // 第二种 批量修改
    countStore.$patch({
        sum:888,
        school:'尚硅谷',
        address:'郑州'
    })
}

第二种通过$patch批量修改,点一次修改一组,提示修改patch一次 

第三种:actions 

适用于大量相同的修改,可以复用 

同理,loveTalk.ts和LoveTalk.vue中

六、storeToRefs 

解释:借助`storeToRefs`将`store`中的数据转为`ref`对象,方便在模板中使用。

注意:`pinia`提供的`storeToRefs`只会将数据做转换,而`Vue`的`toRefs`会转换`store`中数据。

用法:

(1)引入

import { storeToRefs } from "pinia";

(2)使用

// 只会关注数据,不会对方法进行ref包括
const {sum,school,address} = storeToRefs(countStore)

 (3)例如:之前这样写就很冗杂,怎么把countStore去掉呢?

如果直接使用const  {sum,school,address} = countStore.肯定是不行的,会丢失响应式。我们会想到用torefs,但是这里假如用torefs包括的话就会很危险,因为torefs是把所有的数据方法都变成响应式的了。但是我们这里不需要把方法变成响应式,所以就引入了storeToRefs

同理LoveTalk.vue中 

七、getters

1. 概念

当`state`中的数据,需要经过处理后再使用时,可以使用`getters`配置。

2.使用 

有两种方法:

第一种是使用箭头函数 

getters: {
    // 第一种
    // bigSum(state){
    //   return state.sum*10
    // },
    bigSum: (state) => state.sum * 10,
}

第二种是用this 

getters: {
// 第二种 this
    upperSchool():string{
      return this.school.toUpperCase()//变成大写,this相当于store
    }
  },

 这两种方法都要在count.vue中引入,并使用插值语法引用

const {sum,school,address,bigSum,upperSchool} = storeToRefs(countStore)

八、$subscribe()

通过 store 的 `$subscribe()` 方法侦听 `state` 及其变化

在lovetalk.vue中 

talkStore.$subscribe((mutate, state) => {
    console.log('LoveTalk', mutate, state)
    //把数据存储在本地存储防止丢失,
    localStorage.setItem('talk', JSON.stringify(talkList.value))
}),

用stringify是为了把数据转化为字符串存储,否则显示object

如下所示,在本地存储存储成功

 这样我们可以实现刷新不丢失:

在lovetalk.ts中,不要写那些原来的数据,换成以下内容

但是这样还会有一个问题,就是初始的时候没有数据存在, 会报错

可以使用空数组来存初始的

state() {
    return {
      talkList:JSON.parse(localStorage.getItem('talkList') as string) ||[]
    };
  },

 九、store组合写法

以前是这样写的,里面包的actions,state 

组合写法就可以用类似于setup的写法,比较正常,不过最后记得return用到的方法 


import { defineStore } from 'pinia';
import axios from 'axios';
import { nanoid } from 'nanoid';
import { reactive } from 'vue';

export const useTalkStore = defineStore('talk', () => {
  // talkList就是state
  const talkList = reactive(
    JSON.parse(localStorage.getItem('talkList') as string) || []
  );

  // getATalk函数相当于action
  async function getATalk() {
    // 发请求,下面这行的写法是:连续解构赋值+重命名
    let {
      data: { content: title },
    } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json');
    // 把请求回来的字符串,包装成一个对象
    let obj = { id: nanoid(), title };
    // 放到数组中
    talkList.unshift(obj);
  }
  return { talkList, getATalk };
});

 以上仅为个人学习笔记,如有错误请指正

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

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

相关文章

bestvike --bvframe学习

ref title fetch后台api 分页属性&#xff0c;pagination 要差几条&#xff1f;pagelimit 在api中写一个饭方法&#xff0c;vue中用用他 vue.cinfig.js中配置别名 nacos微服务 实体类要继承basedata&#xff08;封装了公共数据&#xff09; 控制器autowired&#xff0c;getm…

哈希函数的简单介绍

哈希函数&#xff1a; hash: 把....弄糟(乱) 又称为散列函数&#xff0c;杂凑函数 什么是哈希表&#xff1f; 哈希表简单来说可以看作是是对数组的升级&#xff0c;&#xff08;也有不少人认为哈希表的本质就是数组&#xff09;&#xff0c;那么哈希表和数组的具体联系和区…

每日OJ题_BFS解决最短路③_力扣127. 单词接龙

目录 ③力扣127. 单词接龙 解析代码 ③力扣127. 单词接龙 127. 单词接龙 难度 困难 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk&#xff1a; 每一对相邻的单词只差一个字母。…

ObjectMapper的具体介绍与使用

文章目录 声明一、前言二、ObjectMapper与JSONObject比较1、核心主要有三个部分&#xff1a;依赖包不同 2、ObjectMapper使用概述2.1、工程的pom.xml导包信息2.2、创建案例中的测试对象2.3、对象和JSON相互转化2.3.1、测试代码2.3.2、测试结果展示 2.4、集合和JSON像话转化2.4.…

简单的车牌号识别

目录 处理流程与界面各接口编写时遇到的一些问题上传图片识别结果标签显示中文 处理流程与界面 首先点击“上传图片”按钮&#xff0c;可以选择文件夹中含有汽车车牌的图片&#xff0c;并显示在“图片框”中。 点击“检测车牌”按钮&#xff0c;会先对“图片框”中即含有汽车车…

Spring Task 定时任务(含结合cron 表达式)

目录 一、Spring Task的介绍 二、使用方法 2.1 配置类启用定时任务支持&#xff1a; 2.2 同步定时任务 ​编辑2.3 fixedRate 可以看出不能满足我们的日常需求 那如何让其开启异步呢&#xff08;开启多个线程工作&#xff09; 三、Spring Task 结合cron表达式 3.1 corn 表…

FreGS:具有渐进频率正则化的3D高斯溅射

FreGS: 3D Gaussian Splatting with Progressive Frequency Regularization FreGS&#xff1a;具有渐进频率正则化的3D高斯溅射 Jiahui Zhang1  Fangneng Zhan2  Muyu Xu1  Shijian Lu1  Eric Xing3, 4 张家慧 1 詹方能 2 许慕玉 1 卢世坚 1 邢志伟 3, 4 1Nanyang Technolo…

Day23_学点儿IDEA_单元测试@Test在新module项目中失效、Jackson核心对象 ObjectMapper识别不到

版本 IntelliJ IDEA 2023.2.4 目录结构 Study(Project) ├──JavaSE(Module) │ └──xxxx └──JavaWeb(Module)└──xxxx问题 1.1 在JavaSE项目中正常可以用的单元测试Test&#xff0c;到了JavaWeb项目中不起作用了 1.2 解决方法 如果是新创建的项目&#xff0c;先…

【Github】一个用于Active Directory的自助密码更改工具

在众多企业的日常运营中&#xff0c;Active Directory&#xff08;AD&#xff09;扮演着核心角色&#xff0c;负责管理和维护员工账户。然而&#xff0c;密码重置作为IT支持团队的常规工作之一&#xff0c;往往既耗时又繁琐。虽然一些商业解决方案和通过Windows服务器上RDS服务…

研究生,该学单片机还是plc。?

PLC门槛相对较低&#xff0c;但是在深入学习和应用时&#xff0c;仍然有很高的技术要求。我这里有一套单片机入门教程&#xff0c;不仅包含了详细的视频 讲解&#xff0c;项目实战。如果你渴望学习单片机&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&am…

【小程序】生成短信中可点击的链接

文章目录 前言一、如何生成链接二、仔细拜读小程序开发文档文档说明1文档说明2 总结 前言 由于线上运营需求&#xff0c;需要给用户发送炮轰短信&#xff0c;用户通过短信点击链接直接跳转进入小程序 一、如何生成链接 先是找了一些三方的&#xff0c;生成的倒是快速&#xf…

vector迭代器失效list迭代器失效

目录 一、vector迭代器失效 1.1插入时的迭代器失效 1.2删除时的迭代器失效 二、list迭代器失效 2.1删除时的迭代器失效 在vector与list的模拟实现中&#xff0c;其中有一问题就是迭代器的失效问题&#xff0c;那么迭代器的失效问题具体是指什么&#xff0c;接下来一探究竟…

【C语言基础】:预处理详解(二)

文章目录 一、宏和函数的对比二、#和##运算符2.1 #运算符2.2 ##运算符 三、#undef四、命令行定义五、条件编译六、头文件的包含1. 头文件包含的方式2. 嵌套文件包含 上期回顾&#xff1a; 【C语言基础】&#xff1a;预处理详解(一) 一、宏和函数的对比 宏通常被应有于执行简单…

系统学c#:1、基础准备(软件下载与安装)

一、Vs软件下载与安装 访问Visual Studio官方网站&#xff1a; https://visualstudio.microsoft.com/zh-hans/downloads 下载Visual Studio 运行exe文件&#xff0c;点击“继续” 初始文件安装完成后选择我们需要安装的项&#xff0c;并勾选好必要的单个组件&#xff0c;设…

VisualStudio2010编译GDAL2.2.4

一、源码目录组织结构 makefile.vc文件是windows下nmake编译工具的makefile文件&#xff0c;nmake.opt是makefile文件的编译选项配置选择文件。 二、打开Visual Studio2010的64位命令行&#xff0c;切换到GDAL224的解压根目录下 输入如下命令回车开始编译源码 nmake -f makef…

Bitwarden 一款开源的密码管理器

Bitwarden Bitwarden 是一款开源的密码管理器&#xff0c;提供强大的安全性和便捷的密码管理功能。 适用于运维、系统较多、密码保密程度较高的场景&#xff01; 主要功能&#xff1a; 密码保存与自动填充&#xff1a;Bitwarden 可以安全地存储您的用户名和密码&#xff0c…

阿里云迁移到AWS云,九河云保姆级教程

随着云计算技术的不断发展,越来越多的企业开始将传统的IT基础设施迁移到云平台上,以获得更高的灵活性、可扩展性和成本效益。在众多云服务提供商中,阿里云和AWS都是备受青睐的选择。本文将探讨如何将阿里云上的资源顺利迁移到AWS云平台,并针对性地进行优化。我们九河云&#xf…

【第9章】@Autowired

文章目录 前言一、Autowired注入1. 属性注入2. 构造方法注入3. set方法注入4. 形参注入5. byName注入5.1 新增实现类5.2 注入 二、Resource1.引入库2.使用2.1 根据注解的name值注入2.2 根据对象变量名注入2.3 根据对象类型注入 总结 前言 【第8章】全注解开发介绍了全注解开发…

电竞陪玩系统开发平台搭建(小程序,公众号,app)线上线下皆有,线下计算距离。

六大核心功能 1.游戏陪练:可以选择当下火爆的游戏内容&#xff0c;选择游戏大神、职业玩家进行陪练&#xff0c;也可约附近路人玩家或是身边的小伙伴语音组队开黑&#xff0c;一起享受边玩游戏边吐槽的无限乐趣。 2.约玩交友:除了游戏陪玩功能&#xff0c;系统还设置了单独的语…

将自己的项目上传至Git

一、安装Git 官网:Git (git-scm.com) 二、注册gitee 官网:工作台 - Gitee.com 进入“我的”出现以下界面 三、创建仓库 点击加号&#xff0c;新建仓库 根据自己的需求取名&#xff0c;描述仓库&#xff0c;开源还是私有&#xff0c;点击创建即可&#xff0c;点击我的即可…