【vue3】15-Vue全家桶-Pinia-更优雅的管理vue状态

news2024/11/23 16:38:44

Pinia状态管理

  • Pinia和Vuex的对比
  • Pinia详解
    • Pinia基本使用
      • 创建pinia
      • 创建Store
    • 核心概念state
      • state基本使用
      • sate其他操作
    • 核心概念getters
      • getters基本使用
      • getters其他操作
    • 核心概念actions
      • actions基本使用
      • actions异步操作

Pinia和Vuex的对比

什么是Pinia呢?

Pinia(发音为/piːnjʌ/,如英语中的“peenya”)是最接近pina(西班牙语中的菠萝)的词;

  • Pinia开始于大概2019年,最初是作为一个实验为Vue重新设计状态管理,让它用起来像组合式APl (Composition API)
  • 从那时到现在,最初的设计原则依然是相同的,并且目前同时兼容Vue2、Vue3,也并不要求你使用Composition API;
  • Pinia本质上依然是一个状态管理的库,用于跨组件、页面进行状态共享(这点和Vuex、Redux一样);

在这里插入图片描述
Pinia和vuex的区别

那么我们不是已经有Vuex了吗?为什么还要用Pinia呢?

  • Pinia最初是为了探索Vuex的下一次迭代会是什么样子,结合了Vuex 5核心团队讨论中的许多想法;
  • 最终,团队意识到Pinia已经实现了Vuex5中大部分内容,所以最终决定用Pinia来替代Vuex;
  • 与vuex相比,Pinia提供了一个更简单的API,具有更少的仪式,提供了Composition-API风格的APl;
  • 最重要的是,在与Typescript一起使用时具有可靠的类型推断支持;

和Vuex相比,Pinia有很多的优势:

  • 比如mutations不再存在:
  • 他们经常被认为是非常冗长;
  • 他们最初带来了devtools集成,但这不再是问题;
  • 更友好的TypeScript支持,Vuex之前对Ts的支持很不友好;
  • 不再有modules的嵌套结构:
    • 你可以灵活使用每一个store,它们是通过扁平化的方式来相互使用的;
  • 也不再有命名空间的概念,不需要记住它们的复杂关系;

在这里插入图片描述

Pinia详解

Pinia基本使用

创建pinia

使用Pinia之前,我们需要先对其进行安装:

yarn add pinia
// or with npm
npm install pinia

创建一个pinia并且将其传递给应用程序:

import { createPinia } from "pinia";

// 创建pinia
const pinia = createPinia()

// 导出pinia
export default pinia

import { createApp } from 'vue'
import App from './App.vue'
import  pinia  from "./stores/index";

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

创建Store

什么是Store?

  • 一个Store (如Pinia)是一个实体,它会持有为绑定到你组件树状态和业务逻辑,也就是保存了全局的状态;
  • 它有点像始终存在,并且每个人都可以读取和写入的组件;
  • 你可以在你的应用程序中定义任意数量的store来管理你的状态;

Store有三个核心概念:

  • state、getters、actions;
  • 等同于组件的data、computed、methods;
  • 一旦store被实例化,你就可以直接在store上访问state、getters和actions中定义的任何属性;

定义一个Store:

  • 我们需要知道Store是使用defineStore()定义的,
  • 并且它需要一个唯一名称,作为第一个参数传递;
//定义关于counter的store 
import { defineStore } from "pinia";

// 一般使用use变量名来接收返回的函数
const useCounter = defineStore("counter", {

    // 1.state
    state: () => ({
        count: 99,
    }),

})

export default useCounter
  • 这个name,也称为id,是必要的,Pinia使用它来将store连接到devtools。
  • defineStore()返回的函数统一使用useXXX作为命名方案, 且XXX一般就使用传入的id,这是约定的规范;
  • 定义完成后导出useXXX
  • 调用defineStore()返回的函数才会创建store

在这里插入图片描述


Store在它被使用之前是不会创建的,我们可以通过调用use函数来使用Store:

<template>
<!-- 展示counterStore.counter的状态 -->
<h2>{{ counterStore.counter }}</h2>
</template>

<script setup>
// 导入我们自定义关于counter的store
import useCounter from '../stores/counter';
// 调用函数才会创建store, 不调用不会创建
const counterStore = useCounter()
</script>

注意Store获取到后不能被解构,那么会失去响应式:

  • 为了从Store 中提取属性同时保持其响应式,需要使用torRefs或者storeToRefs
<script setup>
  import { toRefs } from 'vue';
  import useCounter from '../stores/counter';

  const counterStore = useCounter()
  
  const { counter } = toRefs(counterStore)	//不是响应式
  // 包裹一层toRefs
  const { counter2 } = toRefs(counterStore)//是响应式
  // 或者包裹一层storeToRefs
  const { counter3 } = storeToRefs(counterStore)//是响应式
  
</script>

核心概念state

state基本使用

state 是 store 的核心部分,因为store是用来帮助我们管理状态的。

  • 在 Pinia 中,状态被定义为返回初始状态的函数;

前面创建了一个counter.js文件用于定义counter的store, 接下来我们创建一个urse.js文件, 定义一个用户信息的store来演示state:

import { defineStore } from "pinia";

const userUser = defineStore("user", {
    state: () => ({
        name: "sevgilid",
        age: 18,
        height: 1.88
    })

})

export default userUser

在组件中展示Store:

<template>
  <div class="home">
    <!-- 展示userStore中的状态 -->
    <h2>{{ name }}</h2>
    <!-- 不结构的话这样展示 -->
    <h2>age:{{ userStore.age }}</h2>
    <h2>{{ height }}</h2>
  </div>
</template>

<script setup>
  import { storeToRefs } from 'pinia';
  // 导入我们自定义的store
  import useUser from "../stores/user"

  // 调用函数创建store
  const userStore = useUser()

  // 将store中的状态解构出来
  const { name, height } = storeToRefs(userStore)
</script>

sate其他操作

读取和写入state:

  • 默认情况下,可以通过store 实例访问状态来直接读取和写入状态;
<template>
  <div class="home">
    <!-- 展示userStore中的状态 -->
    <h2>{{ name }}</h2>
    <h2>{{ age }}</h2>
    <h2>{{ height }}</h2>
    <button @click="changeInfo">修改信息</button>
  </div>
</template>

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

  const userStore = useUser()
  const { name, age, height } = storeToRefs(userStore)
  
  function changeInfo() {
    // 使用实例访问状态, 进行修改
    userStore.name = "李大嘴"
    userStore.age = 22
    userStore.height = 1.89
  }
</script>

  • 当我们对某些状态进行了修改之后, 我们可以通过调用 store 上的 $reset() 方法将状态重置到其初始值
    • $reset()方法会将所有的状态重置到初始值
  • 同时修改多个状态
    • 可以调用 $patch 方法 , 它允许您使用部分“state”对象同时应用多个更改;
  • 操作state的数据还有几个方法,替换、订阅等,但都不常见且都是获取过来直接操作就不挨着演示

重置及同时修改多个状态示例:

function changeInfo() {
    userStore.name = "王老五"
    userStore.age = 20
    userStore.height = 1.89
  }

	function resetInfo() {
    // 重置状态
    userStore.$reset()
  }
  
  function changeInfoo() {
    // $patch一次性修改多个状态
    userStore.$patch({
      name: "陈金刚",
      age: 38,
      height: 1.55
    })
  }

核心概念getters

getters基本使用

Getters相当于Store的计算属性:

  • 它们可以用defineStore()中的getters属性定义;
  • getters中可以定义接受一个state作为参数的函数;

在store中定义getters并在其中定义方法:

import { defineStore } from "pinia"

const useCounter = defineStore("counter", {
  state: () => ({
    counter: 125
  }),
  // 定义getters
  getters: {
    doubleCounter(state) {
      return state.counter * 2
    }
  }
})

export default useCounter

直接通过store对象就可以访问当前store的Getters

<template>
  <!-- 访问当前store的Getters -->
  <h2>{{ counterStore.doubleCounter }}</h2>
</template>

<script setup>
  import useCounter from "../stores/counter"

  const counterStore = useCounter()
</script>

getters其他操作

(1)Getters中中访问自己的其他Getters

  • 可以使用this来访问到当前store实例的所有其他属性;
  • this相当于是绑定的store实例

例如在getter中访问自己的doubleCounter:

getters: {
  doubleCounter(state) {
    return state.counter * 2
  },
  doubleCounterAddOne() {
    return this.doubleCounter + 1
  }
}

(2)Getters也可以返回一个函数

const useCounter = defineStore("counter", {
  state: () => ({
    	counter: 101,
        friend: [
            { id: 111, name: "杨楚龙" },
            { id: 112, name: "大武当" },
            { id: 113, name: "吴师傅" },
        ]
  }),
  getters: {
    // getter可以返回一个函数
    getfriendById() {
      return (id) => {
        return this.friend.find(item => item.id == id)
      }
    }
  }
})

<h2>{{ counterStore.getfriendById(111) }}</h2>
<h2>{{ counterStore.getfriendById(112) }}</h2>

(3)当前Getters访问其他store中的state/getters

// 导入usrUser
import useUser from "./user"

const useCounter = defineStore("counter", {
  state: () => ({
    counter: 101
  }),
  
  getters: {
        // 当前Getters访问其他store中的state/getters
            // 比如此处:在counter里想拿到user里的数据
        showMessage(state){
            // -导入后获取userUser里的信息
            const userStore = userUser()
            // -通过state获取自己的信息
            // -实现操作数据:如拼接数据
            return `${state.count}-${userStore.name}`
        }
  }
  
})

<h2>{{ counterStore.showMessage }}</h2>

核心概念actions

actions基本使用

Actions相当于组件中的methods。

  • 可以使用defineStore()中的actions属性定义,并且它们非常适合定义业务逻辑;
  • 和getters一样,在action中可以通过this访问整个store实例的所有操作
  • 不同的是getters里有state参数使用,actions中没有,它的括号是用来传递其余参数的
const useCounter = defineStore("counter", {
  state: () => ({
    counter: 101
  }),
  actions: {
    increment() {
      this.counter++
    }
  }
})

<h2>{{ counterStore.counter }}</h2>
<button @click="changeState">+1</button>

<script setup>
  import useCounter from "../stores/counter"

  const counterStore = useCounter()

  function changeState() {
    // 通过store实例调用即可
    counterStore.increment()
  }
</script>

actions异步操作

Actions中是支持异步操作的,并且我们可以编写异步函数,在函数中使用await

例如在Actions发生网络请求

import { defineStore } from 'pinia'

const useHome = defineStore("home", {
  state: () => ({
    // 定义空数组用于接收网络请求数据
    banners: [],
    recommends: []
  }),
  actions: {
    // 支持异步操作
    async fetchHomeMultidata() {
      // 发送网络请求获取数据
      const res = await fetch("http://123.207.32.32:8000/home/multidata")
      const data = await res.json()

      // 将获取的数据添加到state中
      this.banners = data.data.banner.list
      this.recommends = data.data.recommend.list
    }
  }
})

export default useHome

展示网络请求获取到homeStore中的数据

<template>
  <div class="about">
    <ul v-for="item in homeStore.banners" :key="item.acm">
      <li>{{ item.title }}</li>
    </ul>
  </div>
</template>

<script setup>
  import useHome from "../stores/home"

  const homeStore = useHome()

  // 告知发送网络请求
  homeStore.fetchHomeMultidata().then(res => {
    console.log("fetchHomeMultidata的action已经完成了:", res)  
    //这是确认获取数据,打印一下  res是异步函数返回的值
  })
</script>

(这里涉及到一些异步函数和promise的前置知识)

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

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

相关文章

使用OPC UA客户端工具Softing OPC Client读写OPC节点数据

Softing OPC Client工具介绍 Softing OPC Client工具是德国Softing公司出品的标准OPC客户端。是最完备的OPC UA客户端工具。全部的数据类型都支持,功能齐备。是查看或测试OPC服务器的最好工具了。功能齐全、使用方便、而且免费 官方下载地址: https://industrial.softing.co…

AI视频融合平台EasyCVR添加上级平台提示语出现错位现象的排查与优化

EasyCVR视频融合平台基于云边端一体化架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;平台支持多协议、多类型的设备接入&#xff0c;包括主流标准协议国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大…

web自动化测试——pytest快速上手

目录 1. pytest 1.1 安装 1.2 验证安装 1.3 pytest文档 1.4 创建测试用例 1.5 执行测试用例 1.5.1 使用命令行执行 1.5.2 IDE&#xff08;PyChram&#xff09;执行 1.5.3 执行指定文件指定方法 1.5.3.1 命令行编写方式 1.5.3.2 pycharm 编写方式 1.5.4 带参数执行 …

spring Cloud使用Skywalking搭建笔记

skywalking支持dubbo&#xff0c;SpringCloud&#xff0c;SpringBoot集成&#xff0c;代码无侵入&#xff0c;通信方式采用GRPC&#xff0c;性能较好&#xff0c;实现方式是java探针&#xff0c;支持告警&#xff0c;支持JVM监控&#xff0c;支持全局调用统计等等&#xff0c;功…

品牌方的brief怎么写,注意事项

我们都知道&#xff0c;对于产品传播来说&#xff0c;达人起着重要的作用。可又是什么影响着达人的传播结果呢?今天给大家分享下&#xff0c;品牌方的brief怎么写的注意事项。 一、什么是brief 可能有的朋友&#xff0c;还不太清楚&#xff0c;到底什么是brief。Brief&#xf…

【openGauss数据库】---设置开机自启动openGauss数据库服务

【openGauss数据库】---设置开机自启动openGauss数据库服务 &#x1f53b; 一、openGauss 自定义服务的配置文件了解&#x1f53b; 二、设置openGauss 开机自启动&#x1f53b; 三、总结—温故知新 &#x1f448;【上一篇】 &#x1f496;The Begin&#x1f496; 点点关注&am…

基于边缘计算AidLux的自动驾驶智能预警应用方案

上传源码至AidLux&#xff08;具体操作见前面AIGC帖子&#xff09; 配置环境&#xff1a; cd YOLOP/YOLOP pip install -r requirements.txt pip install torch1.8.1 torchvision0.9.1 -i https://pypi.mirrors.ustc.edu.cn/simple/ pip install onnxruntime -i https://py…

Linux--删除目录:

一、删除空目录&#xff1a;rmdir rmdir是remove director的简写 语法&#xff1a; rmdir 目录名 功能&#xff1a; 删除空目录 示例&#xff1a; 删除空目录&#xff1a;成功 删除非空目录&#xff1a;失败 删除一切&#xff1a;rm 语法&#xff1a; 1.rm 文件名2.rm -r…

Unity wav2Audioclip知识点记录

链接&#xff1a;hanachiru/Wav2AudioClipSample: Sample project to convert Wav files to AudioClip. (github.com) public static class Wav {/// <summary>/// Create AudioClip/// </summary>/// <param name"fileBytes">.wav</param>/…

ajax根据经纬度 获取地址

address 参数格式&#xff0c;经度在前&#xff0c;维度在后&#xff0c;以逗号隔开。 开放地址&#xff0c;有可能失效 var address 30.67,104.06; //经纬度格式一 //var address11620.12’,3912.34’;//经纬度格式二 var url "http://api.map.baidu.com/geocoder/…

什么台灯护眼效果好?注意这些选灯细节!

每个人对一个事物的接受能力跟使用体验是不一样的&#xff0c;但是护眼灯可以说是大部分人使用下来都觉得好用的产品&#xff0c;我自己大学毕业后&#xff0c;面对电脑比较多&#xff0c;我也会买个护眼台灯用&#xff0c;可以舒缓眼部疲劳&#xff0c;给孩子使用也是&#xf…

【【51单片机的DS1302模块-9】】

51单片机的DS1302模块使用 DS1302时钟显示 显示年月日 时钟秒 再可以通过按键调节时间 有种当初买的小手表的感觉 其实我们芯片内部也是可以用计时的&#xff0c;但是过分占用了芯片内部的计时模块&#xff0c;我们不如通过外部的时间模块DS1302来操作 单片机的定时器不能掉电…

Linux教程——Linux用户和用户组(包含两者之间的关系)

Linux 是多用户多任务操作系统&#xff0c;换句话说&#xff0c;Linux 系统支持多个用户在同一时间内登陆&#xff0c;不同用户可以执行不同的任务&#xff0c;并且互不影响。 例如&#xff0c;某台 Linux 服务器上有 4 个用户&#xff0c;分别是 root、www、ftp 和 mysql&…

想知道通行密钥如何取代密码吗?看完这篇文章你就懂了

密码作为一种广泛应用的身份验证方式&#xff0c;已经成为我们日常生活中不可或缺的一部分。然而&#xff0c;随着技术的不断发展和安全威胁的增加&#xff0c;传统的用户名-密码组合逐渐显示出一些弊端。幸运的是&#xff0c;通行密钥作为一种新兴的身份验证方法&#xff0c;正…

Springboot 处理BigDecimal 数据科学计数格式,展示E+8的问题

如图&#xff1a; 处理方式&#xff1a; 我们基于springboot的 JsonSerializer &#xff0c;我们自定义一下 针对BigDecimal类型属性的JsonSerializer处理。 import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import…

vue 3.0 + vite + flv 视频流播放

官方提供的 demo 地址&#xff0c;大家可以用自己的流地址&#xff0c;先试试是否符合需求&#xff1b; http://bilibili.github.io/flv.js/demo/ Flv.js API https://gitee.com/mirrors/flv.js/blob/master/docs/api.md 安装 Flv.js npm install --save flv.js更改 tscon…

CASAIM 与ABB 达成三维数字化测量技术合作,CASAIM 国有专业尺寸检测实验室助力机器人轨道检测

近期&#xff0c;CASAIM与ABB达成三维数字化测量技术合作&#xff0c;CASAIM 国有专业尺寸检测实验室助力ABB完成机器人轨道检测&#xff0c;提高机器人的运动精度和稳定性。 ABB集团位列全球500强企业&#xff0c;是全球领先的工业机器人制造商之一&#xff0c;致力于提供高质…

ModaHub魔搭社区:向量数据库Milvus部署运维问题教程(二)

目录 在 Windows 安装 pymilvus 报错&#xff0c;如何解决&#xff1f; 内网环境&#xff0c;即离线方式&#xff0c;能否部署 Milvus 服务&#xff1f; 在多个 Milvus 节点接入 Pushgateway 的情况下如何进行区分数据来源&#xff1f; 我应该使用 SQLite 还是 MySQL 进行元…

基于群组实现从 Azure AD 到极狐GitLab 的单点登录

目录 配置单点登录 在 Azure AD 中创建企业应用 SAML 基础配置 配置 Azure “Attributes & Claims” 配置用户同步 在极狐GitLab 创建 SCIM Token 配置 Azure Provisioning Azure 手动用户预配 测试单点登录 Azure 自动用户同步 配置群组同步 配置 SAML 群组链…

【算法基础】快速排序(模板)

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;【C/C】算法 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵 希望大佬指点一二 如果文章对你有…