Pinia状态管理

news2024/10/5 22:50:31

1、Pinia和Vuex的对比

1.1、什么是Pinia呢?

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

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

1.2、Pinia和Vuex的区别 

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

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

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

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

1.3、如何使用Pinia? 

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

yarn add pinia
# 或者使用 npm
npm install pinia

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

 

2、创建Pinia的Store 

2.1、认识Store

什么是Store?

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

Store有三个核心概念:

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

2.2、定义一个Store

定义一个Store:

  • 我们需要知道 Store 是使用 defineStore() 定义的
  • 并且它需要一个唯一名称,作为第一个参数传递;

这个 name,也称为 id,是必要的,Pinia 使用它来将 store 连接到 devtools。

返回的函数统一使用useX作为命名方案,这是约定的规范;

2.3、使用定义的Store

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

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

  • 为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()。 

2.4、示例代码 

index.js

import {createPinia} from 'pinia'
// 创建pinia
const pinia = createPinia()
export default pinia

counter.js

// 定义关于counter的store
import {defineStore} from 'pinia'

// 参数一为标识名
// 返回值为一个函数
const useCounter = defineStore("counter", {
    state: () => ({
        count: 99
    })
})

export default useCounter

Home.vue

<template>
  <div class="home">
    <h2>Home View</h2>
    <h2>count: {{ counterStore.count }}</h2>
    <h2>count: {{ count }}</h2>
    <button @click="incrementCount">count+1</button>
  </div>
</template>

<script setup>
  import {toRefs} from 'vue'
  import {storeToRefs} from 'pinia'
  import useCounter from '@/stores/counter';

  // 调用函数,拿到store对象
  const counterStore = useCounter()

  // 解构对象(解构出来的对象会失去响应式)
  // const { count } = toRefs(counterStore)
  // storeToRefs这是vue提供的,作用与toRefs相同
  const {count} = storeToRefs(counterStore)


  // 修改数据
  function incrementCount() {
    counterStore.count++
  }

</script>

<style scoped>
</style>

App.vue

<template>
  <div class="app">
    <h2>App Component</h2>
    <hr>
    <home/>
  </div>
</template>

<script setup>

  import Home from './views/Home.vue'

</script>

<style>

</style>

main.js

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

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

注意:index.js、App.vue、main.js接下来都不会发生改变了,所以下面的示例代码就不会写出来了。

3、Pinia核心概念State

3.1、认识和定义State

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

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

3.2、操作State(一) 

读取和写入 state:

  • 默认情况下,您可以通过 store 实例访问状态来直接读取和写入状态;

重置 State:

  • 你可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值; 

3.3、操作State(二) 

改变State:

  • 除了直接用 store.counter++ 修改 store,你还可以调用 $patch 方法;
  • 它允许您使用部分“state”对象同时应用多个更改

替换State:

  • 您可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态: 

3.4、代码示例 

Home.vue

<template>
  <div class="home">
    <h2>Home View</h2>
    <h2>name: {{ name }}</h2>
    <h2>age: {{ age }}</h2>
    <h2>level: {{ level }}</h2>
    <button @click="changeState">修改state</button>
    <button @click="resetState">重置state</button>
  </div>
</template>

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

  const userStore = useUser()
  const {name, age, level} = storeToRefs(userStore)

  function changeState() {
    // 1.一个个修改状态
    // userStore.name = "kobe"
    // userStore.age = 20
    // userStore.level = 200

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

    // 3.替换state为新的对象
    const oldState = userStore.$state
    userStore.$state = {
      name: "curry",
      level: 200
    }
    console.log(oldState === userStore.$state)
  }

  function resetState() {
    userStore.$reset() // 重置state
  }

</script>

<style scoped>
</style>

user.js

import {defineStore} from 'pinia'

const useUser = defineStore("user", {
    state: () => ({
        name: "why",
        age: 18,
        level: 100
    })
})

export default useUser

4、Pinia核心概念Getters

4.1、认识和定义Getters

Getters相当于Store的计算属性:

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

4.2、访问Getters(一) 

访问当前store的Getters:

Getters中访问自己的其他Getters:

  • 我们可以通过this来访问到当前store实例的所有其他属性; 

访问其他store的Getters:

4.3、访问Getters(二) 

Getters也可以返回一个函数,这样就可以接受参数:

4.4、代码示例 

counter.js

// 定义关于counter的store
import {defineStore} from 'pinia'

import useUser from './user.js'

const useCounter = defineStore("counter", {
    state: () => ({
        count: 99,
        friends: [
            {id: 111, name: "why"},
            {id: 112, name: "kobe"},
            {id: 113, name: "james"},
        ]
    }),
    getters: {
        // 1.基本使用
        doubleCount(state) {
            return state.count * 2
        },
        // 2.一个getter引入另外一个getter
        doubleCountAddOne() {
            // this是store实例
            return this.doubleCount + 1
        },
        // 3.getters也支持返回一个函数
        getFriendById(state) {
            return function (id) {
                for (let i = 0; i < state.friends.length; i++) {
                    const friend = state.friends[i]
                    if (friend.id === id) {
                        return friend
                    }
                }
            }
        },
        // 4.getters中用到别的store中的数据
        showMessage(state) {
            // 1.获取user信息
            const userStore = useUser()

            // 2.获取自己的信息

            // 3.拼接信息
            return `name:${userStore.name}-count:${state.count}`
        }
    }
})

export default useCounter

Home.vue 

<template>
  <div class="home">
    <h2>Home View</h2>
    <h2>doubleCount: {{ counterStore.doubleCount }}</h2>
    <h2>doubleCountAddOne: {{ counterStore.doubleCountAddOne }}</h2>
    <h2>friend-111: {{ counterStore.getFriendById(111) }}</h2>
    <h2>friend-112: {{ counterStore.getFriendById(112) }}</h2>
    <h2>showMessage: {{ counterStore.showMessage }}</h2>
    <button @click="changeState">修改state</button>
    <button @click="resetState">重置state</button>
  </div>
</template>

<script setup>
  import useCounter from '@/stores/counter';

  const counterStore = useCounter()

</script>

<style scoped>
</style>

5、Pinia核心概念Actions

5.1、认识和定义Actions

Actions 相当于组件中的 methods。

  • 可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑;

和getters一样,在action中可以通过this访问整个store实例的所有操作; 

5.2、Actions执行异步操作 

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

5.3、代码示例 

counter.js 

// 定义关于counter的store
import {defineStore} from 'pinia'

import useUser from './user'

const useCounter = defineStore("counter", {
    state: () => ({
        count: 99,
        friends: [
            {id: 111, name: "why"},
            {id: 112, name: "kobe"},
            {id: 113, name: "james"},
        ]
    }),
    getters: {
        // 1.基本使用
        doubleCount(state) {
            return state.count * 2
        },
        // 2.一个getter引入另外一个getter
        doubleCountAddOne() {
            // this是store实例
            return this.doubleCount + 1
        },
        // 3.getters也支持返回一个函数
        getFriendById(state) {
            return function (id) {
                for (let i = 0; i < state.friends.length; i++) {
                    const friend = state.friends[i]
                    if (friend.id === id) {
                        return friend
                    }
                }
            }
        },
        // 4.getters中用到别的store中的数据
        showMessage(state) {
            // 1.获取user信息
            const userStore = useUser()

            // 2.获取自己的信息

            // 3.拼接信息
            return `name:${userStore.name}-count:${state.count}`
        }
    },
    actions: {
        increment() {
            this.count++
        },
        incrementNum(num) {
            this.count += num
        }
    }
})

export default useCounter

home.js

import {defineStore} from 'pinia'

const useHome = defineStore("home", {
    state: () => ({
        banners: [],
        recommends: []
    }),
    actions: {
        async fetchHomeMultidata() {
            // fetchHomeMultidata() {
            const res = await fetch("http://123.207.32.32:8000/home/multidata")
            const data = await res.json()

            this.banners = data.data.banner.list
            this.recommends = data.data.recommend.list

            // return new Promise(async (resolve, reject) => {
            //   const res = await fetch("http://123.207.32.32:8000/home/multidata")
            //   const data = await res.json()

            //   this.banners = data.data.banner.list
            //   this.recommends = data.data.recommend.list

            //   resolve("bbb")
            // })
        }
    }
})

export default useHome

Home.vue

<template>
  <div class="home">
    <h2>Home View</h2>
    <h2>doubleCount: {{ counterStore.count }}</h2>
    <button @click="changeState">修改state</button>

    <!-- 展示数据 -->
    <h2>轮播的数据</h2>
    <ul>
      <template v-for="item in homeStore.banners">
        <li>{{ item.title }}</li>
      </template>
    </ul>
  </div>
</template>

<script setup>
  import useCounter from '@/stores/counter';
  import useHome from '@/stores/home';

  const counterStore = useCounter()

  function changeState() {
    // counterStore.increment()
    counterStore.incrementNum(10)
  }

  const homeStore = useHome()
  homeStore.fetchHomeMultidata().then(res => {
    console.log("fetchHomeMultidata的action已经完成了:", res)
  })

</script>

<style scoped>
</style>

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

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

相关文章

Linux使用操作

文章目录各类小技巧&#xff08;快捷键&#xff09;软件安装systemctl软连接日期、时区IP地址、主机名IP地址和主机名虚拟机配置固定IP网络传输下载和网络请求端口进程管理主机状态环境变量上传、下载压缩、解压各类小技巧&#xff08;快捷键&#xff09; 强制停止 Linux某些程…

python语法 dot函数

dot是numpy里的函数&#xff0c;主要用于求向量相乘&#xff0c;矩阵乘法&#xff0c;矩阵与向量乘法一、一维向量相乘要求元素个数相同&#xff0c;相当于求内积&#xff0c;对应元素相乘再相加&#xff0c;“1*3 2*4 11”二、矩阵和矩阵相乘遵循矩阵乘法法则“左行 * 右列”…

高通平台开发系列讲解(WIFI篇)什么是WLAN无线局域网

文章目录 一、什么是WLAN1.1、WLAN发展史1.2、WLAN工作频段二、高通相关文件2.1、配置文件2.2、开机启动2.3、wpa_supplicant沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本文将基于高通平台介绍什么是无线局域网。 一、什么是WLAN 在WLAN领域被大规模推广和商用的是…

【编程入门】开源记事本(鸿蒙Java版)

背景 前面已输出多个系列&#xff1a; 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 本系列对比云笔记&#xff0c;将更为简化&#xff0c;去掉了网络调用&#xff0…

WebSocket 入门:简易聊天室

大家好&#xff0c;我是前端西瓜哥&#xff0c;今天我们用 WebSocket 来实现一个简单的聊天室。 WebSocket 是一个应用层协议&#xff0c;有点类似 HTTP。但和 HTTP 不一样的是&#xff0c;它支持真正的全双工&#xff0c;即不仅客户端可以主动发消息给服务端&#xff0c;服务…

基于Tkinter制作简易的串口bootloader上位机

文章目录前言1.测试设备1.1 UART Bootloaer软件架构图1.2 UART Bootloader流程图1.3 通信数据处理1.3.1 S19文件的简单介绍1.3.2 S19文件的传输方式1.3.2 接收数据之后的处理1.4 链接文件设置1.4.1 Bootloader设置1.4.2 Application设置2.上位机2.1 参考资料2.2 Tkinter简介2.3…

C++初阶:vector类

文章目录1 vector介绍2 实现vector2.1 类的定义2.2 默认成员函数2.2.1 构造函数2.2.2 析构函数2.2.3 拷贝构造2.2.4 赋值重载2.3访问接口2.4 容量接口2.5 修改接口2.5.1 尾插尾删2.5.2 任意位置插入2.5.3 任意位置删除2.6 其他接口1 vector介绍 1 vector是表示可变大小数组的序…

每日学术速递1.26

CV - 计算机视觉 今天带来的是北航IRIP实验室被国际人工智能联合会议IJCAI-ECAI 2022接收的3篇论文。 IJCAI 是人工智能领域中最主要的学术会议之一&#xff0c;原为单数年召开&#xff0c;自2015年起改为每年召开&#xff0c;本次IJCAI与ECAI一起召开。IJCAI官网显示&#xf…

【Linux】冯诺依曼体系结构与操作系统概念理解

&#x1f451;作者主页&#xff1a;安 度 因 &#x1f3e0;学习社区&#xff1a;StackFrame &#x1f4d6;专栏链接&#xff1a;Linux 文章目录一、前言二、冯诺依曼体系结构1、体系简述2、内存的重要性3、硬件方案解释软件行为4、体系结构中的数据流动5、拓展三、操作系统简述…

ch1 操作系统启动

lab1 实验准备 按照实验解压后进入oslab中&#xff0c;按照make编译。 cd /home/shiyanlou/oslab/ tar -zxvf hit-oslab-linux-20110823.tar.gz \-C /home/shiyanlou/ ./run cd ./linux-0.11/ make all make clean ..... make all运行脚本即可启动内核 调试 汇编级调试和C语…

贪心算法的题目

每一步都做出一个局部最优的选择&#xff0c;最终的结果就是全局最优 只有一部分问题才能用贪心算法&#xff08;严格来讲&#xff0c;一个问题能不能用贪心算法需要证明的&#xff09; 2022.8.30 蔚来笔试题&#xff1a; 有a个y,b个o,c个u,用这些字母拼成一个字符串&#xf…

Anaconda软件中的 Environments 及 Jupyter Lab使用方法介绍

来源&#xff1a;投稿 作者&#xff1a;助教-Frank 编辑&#xff1a;学姐 本篇是打造舒适的AI开发环境系列-软件篇1 上期内容&#xff1a;学人工智能电脑&主机八大件配置选择指南 本文的重点&#xff1a; (1)Environments使用中如何安装python包.; (2)Jupyter Lab如何在…

Kettle(6):表输入组件——mysql转mysql

1 需求 前面我们已经将Excel中数据抽取到了MySQL的t_user表中。 现在有了新需求&#xff0c;要将MySQL数据库中的 t_user 表中的数据抽取出来&#xff0c;装载到另外一张表 t_user1中。 2 构建Kettle数据流图 2.1 从核心对象的输入组件中&#xff0c;将「表输入」组件拖拽到中…

电脑下载软件用什么软件好?安卓手机下载软件用哪个软件好?IDM下载器说:在做的都是弟弟

大年初五&#xff0c;迎财神&#xff0c;先祝大家新的一年财源滚滚&#xff0c;接下来为大家分享超级经典的IDM下载器&#xff0c;电脑端毫无争议的下载工具&#xff0c;安卓平台idm也是力压群雄&#xff0c;下面就为大家详细分享下&#xff1a; 1&#xff1a;1DM下载器&#x…

微服务统一登陆认证怎么做

[微服务统一登陆认证怎么做}&#xff1f;JWT 无状态登录原理 1.1.什么是有状态&#xff1f; 有状态服务&#xff0c;即服务端需要记录每次会话的客户端信息&#xff0c;从而识别客户端身份&#xff0c;根据用户身份进行请求的处理&#xff0c;典型的设计如tomcat中的session…

notepad++在行首行尾添加字符 | 选中列

目录 1、首行/尾行添加字符 1【使用快捷键 CtrlH】 2【^为行首、$为行尾】 3、查找模式选中正则表达式 2、Notepad中列选(竖选&#xff09; 1、首行/尾行添加字符 1【使用快捷键 CtrlH】 或者鼠标 2【^为行首、$为行尾】 3、查找模式选中正则表达式 2、Notepad中列选(竖…

深度学习入门(一)感知机

该文将介绍感知机A&#xff08;perceptron&#xff09;这一算法。感知机是由美国学者Frank Rosenblatt在1957年提出来的。为何我们现在还要学习这一很久以前就有的 算 法 呢 &#xff1f; 因 为 感 知 机 也 是 作 为 神 经 网 络&#xff08;深 度 学 习&#xff09;的起源的算…

详解Windows通过命令行查看电脑连接过的WIfI密码

CONTENT打开命令行进入命令行下的netsh工具查看连接过的WiFi名称指定WiFi名称查看密码在Windows操作系统中&#xff08;PS&#xff1a;Windows Vista及以后的Windows系统&#xff09;可以通过命令行工具netsh查看和更改电脑的无线连接设置&#xff0c;包括WiFi。本篇博客将详细…

C语言进阶——文件管理

每当我们写好一段代码运行结束之后&#xff0c;再次运行的时候就会发现&#xff0c;之前在终端上输入的数据都会消失&#xff0c;那么如何把之前输入的数据保存下来呢&#xff1f; 我们一般把数据持久化的方式有把数据存放在磁盘文件中、存放到数据库。打印等方式进行保存。 …

Java---微服务---elasticsearch安装部署

elasticsearch安装部署1.部署单点es1.1.创建网络1.2.加载镜像1.3.运行2.部署kibana2.1.部署2.2.DevTools3.安装IK分词器3.1.在线安装ik插件&#xff08;较慢&#xff09;3.2.离线安装ik插件&#xff08;推荐&#xff09;1&#xff09;查看数据卷目录2&#xff09;下载并解压缩分…