Vue3(四):Pinia

一、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 };
});

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

外网如何访问内网数据库?

在当今信息时代&#xff0c;随着互联网的快速发展&#xff0c;很多企业和个人都面临着外网访问内网数据库的需求。外网访问内网数据库可以实现远程操作&#xff0c;方便用户在任何地点使用移动设备进行数据管理和查询。本文将介绍一种名为【天联】的组网产品&#xff0c;它是一…

Sublime Text下载,安装,安装插件管理器,下载汉化插件

SublimeTest官网 © Sublime Text中文网 下载安装 一路点击安装即可 安装插件管理器 管理器官网安装 - 包控制 (packagecontrol.io) 手动安装将3 位置点击网址下载 再打开SublimeTest 点击 选择第一个Browse Packages..... 将会跳转到文件夹中 进入上一个文件夹 在进入…

使用剧本批量部署rsync服务端实战

目录 1、实战部署 编写剧本 执行剧本测试&#xff01;&#xff01;&#xff01; 2、部署方式对比 1、实战部署 编写剧本 执行剧本测试&#xff01;&#xff01;&#xff01; 2、部署方式对比 ansible模块实战-部署rsync服务端-CSDN博客 ansible临时命令和playbook区别 …

UE5 C++ TimeLine 时间轴练习

一. Actor引入头文件 #include "Components/TimelineComponent.h" 声明CurveFloat 和 TimelineComponent UPROPERTY(EditAnywhere,BlueprintReadWrite,Category "MyCurve")UCurveFloat* MyCurveFloat;UPROPERTY(EditAnywhere, BlueprintReadWrite, Cate…

北漂程序员整理:2024年阿里云服务器租用优惠价格表

阿里云服务器租用价格表2024年最新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核…

逻辑卷和磁盘配额

文章目录 一、逻辑卷二、磁盘配额 一、逻辑卷 为什么会出现技术&#xff1f; 分区的缺点&#xff1a; 没有备份功能无法扩容性能取决于硬盘本身 相关概念 LVM 是 Logical Volume Manager 的简称&#xff0c;译为中文就是逻辑卷管理。它是 Linux 下对硬盘分区的一种管理机制。…

【深度学习】深度学习md笔记总结第5篇:神经网络与tf.keras,学习目标【附代码文档】

深度学习笔记完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;深度学习课程&#xff0c;深度学习介绍要求,目标,学习目标,1.1.1 区别,学习目标,学习目标。TensorFlow介绍&#xff0c;2.4 张量学习目标,2.4.1 张量(Tensor),2.4.2 创建张量的指令,2.4.3 张量…

OpenKylin设置root密码

前言 新安装的OpenKylin系统应该root用户没有设置密码&#xff0c;但是可以使用sudo -i 临时获取root权限&#xff0c;不影响正常使用 当前是root用户 1、终端输入passwd命令 passwd2、按照提示输入新密码和确认密码 当前非root用户 1、终端输入sudo passwd root 命令 s…

2022年电赛F题23年电赛D题-信号调制度测量装置说明中提到带通采样定律。

2022年电赛F题-信号调制度测量装置说明中提到带通采样定律。 23年电赛D题十分相似&#xff0c;但是22年载波达到了10M&#xff0c;根据奈奎斯特采样定理&#xff0c;我们知道想要分析出频谱不混叠的频谱图&#xff0c;采样率必须大于最大谐波的二倍。那么就意味着AD采样率要大…

【笔试训练】day2

文章目录 1.牛牛的快递代码&#xff1a; 2.最小花费爬楼梯思路&#xff1a;代码&#xff1a; 3.数组中两个字符串的最小距离思路&#xff1a;代码&#xff1a; 1.牛牛的快递 注意一个坑&#xff0c;首先就是加急是总共加5块&#xff0c;不是每千克加5块。 思路呃&#xff0c;没…

Java SpringBoot基于微信小程序的高速公路服务区充电桩在线预定系统,附源码

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

6. Django 深入模板

6. 深入模板 6.1 Django模板引擎 Django内置的模板引擎包含模板上下文(亦可称为模板变量), 标签和过滤器, 各个功能说明如下: ● 模板上下文是以变量的形式写入模板文件里面, 变量值由视图函数或视图类传递所得. ● 标签是对模板上下文进行控制输出, 比如模板上下文的判断和循…

初级软件测试常见问题

1.JMeter &#xff08;1&#xff09;在http请求的时候&#xff0c;消息体数据中的数据需要用{}和“”标记起来&#xff0c;变量要用${}括起来。 &#xff08;2&#xff09;在响应断言的时候&#xff0c;要根据测试模式输出的内容来改变测试字段&#xff0c;假如输出错误可以把…

hadoop编程之工资序列化排序

数据集展示 7369SMITHCLERK79021980/12/17800207499ALLENSALESMAN76981981/2/201600300307521WARDSALESMAN76981981/2/221250500307566JONESMANAGER78391981/4/22975207654MARTINSALESMAN76981981/9/2812501400307698BLAKEMANAGER78391981/5/12850307782CLARKMANAGER78391981/…

attention and tell论文【无标题】

这个公式使用LaTeX语法表示为&#xff1a; ( i t f t o t c t ) ( σ σ σ tanh ⁡ ) T D m n , n ( E y t − 1 h t − 1 x t ) \begin{pmatrix}i_t \\f_t \\o_t \\c_t\end{pmatrix} \begin{pmatrix}\sigma \\\sigma \\\sigma \\\tanh\end{pmatrix}T_{Dmn,n}\begin{pmatri…

代码随想录Day41:动态规划Part3

Leetcode 343. 整数拆分 讲解前&#xff1a; 毫无头绪 讲解后&#xff1a; 这道题的动态思路一开始很不容易想出来&#xff0c;虽然dp数组的定义如果知道是动态规划的话估摸着可以想出来那就是很straight forward dp定义&#xff1a;一维数组dp[i], i 代表整数的值&#xf…

5.paramiko模块使用

目录 概述实践安装paramikoparamiko包括两个核心的组件paramiko有几个基础的名词 SSHClient使用常用方法例子例子2 SFTPClient类案例 结束 概述 paramiko是实现远程控制 实践 安装 pip install paramiko paramiko SSH是一个协议&#xff0c;paramiko是使用SSHv2协议(底层使…

OpenCV基本图像处理操作(一)——图像基本操作与形态学操作

环境配置地址 图像显示 import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB imgcv2.imread(cat.jpg) img_gray cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) img_gray.shape cv2.imshow("img_gray", img_gray) cv2…

Deep Learning for Single Image Super-Resolution: A Brief Review

TMM 2019 用深度学习来解决SISR问题(single image super resolution)的问题&#xff0c;从两个方面 高效的网络结构&#xff0c;efficient architectures&#xff1b;有效的优化目标&#xff0c;OPTIMIZATION OBJECTIVES&#xff1b; 问题的定义 由LR y y y恢复HR x x x&a…

c++总结笔记(一)

计算机可以将程序转化为二进制指令&#xff08;即机器码&#xff09;&#xff0c;并由CPU执行&#xff0c;CPU会按照指令的顺序依次执行每个指令。 C语言特点&#xff1a; 简洁高效可移植模块化标准化 C语言的标准 C89(C90)标准C99标准C11标准 导入 使用include导入包含…