0


Vue中的Pinia状态管理工具 | 一篇文章教会你全部使用细节

文章目录

Pinia状态管理

Pinia和Vuex的对比

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

Pinia开始于大概2019年,最初是

作为一个实验为Vue重新设计状态管理

,让它用起来适合组合式API(Composition API)。

从那时到现在,最初的设计原则依然是相同的,并且目前同时兼容Vue2、Vue3,也并不要求你使用Composition API;

Pinia本质上依然是一个状态管理的库,用于

跨组件、页面

进行状态共享(这点和Vuex、Redux一样);

那么我们不是已经有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,它们是通过扁平化的方式来相互使用的;

优势四: 也不再有命名空间的概念,不需要记住它们的复杂关系;

在这里插入图片描述

Pinia基本使用

🍤创建Pinia

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

yarn add pinia
npm install pinia

使用pinia我们需要在单独的js文件中创建一个pinia, 并且在main.js中将其注册, 如下:

这样我们项目中就已经存在pinia了

import{ createPinia }from"pinia";// 创建piniaconst pinia =createPinia()// 导出piniaexportdefault pinia
import{ createApp }from'vue'import App from'./App.vue'// 导入piniaimport pinia from'./stores'const app =createApp(App)// 注册pinia
app.use(pinia)
app.mount('#app')

🍤创建Store

什么是Store?

一个 Store (如 Pinia)是一个实体,它会持有为绑定到你组件树的状态和业务逻辑,也就是保存了全局的状态;

它有点像始终存在,并且每个人都可以读取和写入的组件;

你可以在你的应用程序中定义

任意数量的Store

来管理你的状态;

**Store有三个核心概念(接下来会一一讲到)**:

state、getters、actions;

等同于组件的data、computed、methods;

一旦 store 被实例化,你就

可以直接在 store 上访问 state、getters 和 actions 中定义的任何属性

定义一个Store

Store 是使用 defineStore() 定义的, 我们一般都会在一个单独的js的文件创建store, 不同组件的数据, 我们会定义在不同的js文件中创建不同的store

由于pinia中可以定义多个store, 所以每一个store它都需要一个

唯一名称

,作为第一个参数传递;

// 定义关于counter的storeimport{ defineStore }from"pinia"// 调用defineStore定义store, defineStore返回一个函数const useCounter =defineStore("counter",{state:()=>({counter:101})})// 将useCounter函数导出exportdefault useCounter

**第一个参数 name,也称为 id,

是必要的

,Pinia 使用它来将 store 连接到 devtools**。

**defineStore()返回的函数统一使用

useXXX

作为命名方案, 且XXX一般就使用传入的id,这是约定的规范**;

调用defineStore()返回的函数才会创建store


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

<template><!-- 展示counterStore.counter的状态 --><h2>{{ counterStore.counter }}</h2></template><scriptsetup>// 导入我们自定义关于counter的storeimport useCounter from'../stores/counter';// 调用函数才会创建store, 不调用不会创建const counterStore =useCounter()</script>

注意Store获取到后, 如果我们想要对其解构, 不能直接解构,直接解构的话会失去响应式

为了从 Store 中提取属性同时保持其响应式我们有两种方式

  • 方式一: 解构时包裹一层toRefs
  • 方式二: pinia给我们提供了一个方法, 使用storeToRefs()方法可以保持数据的响应式。

方式一

<script setup>import{ toRefs }from'vue';import useCounter from'../stores/counter';const counterStore =useCounter()// 包裹一层toRefsconst{ counter }=toRefs(counterStore)</script>

方式二

<script setup>import{ storeToRefs }from'pinia';import useCounter from'../stores/counter';const counterStore =useCounter()// 包裹一层storeToRefsconst{ counter }=storeToRefs(counterStore)</script>

Pinia核心概念State

🍟state基本使用

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

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

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

在pinia中state和vuex中一样, state是一个函数, 返回一个对象

import{ defineStore }from"pinia"const useUser =defineStore("user",{// state定义状态state:()=>({name:"chenyq",age:18,height:1.88})})exportdefault useUser

将定义的Store展示到组件中

<template><divclass="home"><!-- 展示userStore中的状态 --><h2>{{ name }}</h2><h2>{{ age }}</h2><h2>{{ height }}</h2></div></template><scriptsetup>import{ storeToRefs }from'pinia';// 导入我们自定义的storeimport useUser from"../stores/user"// 调用函数创建storeconst userStore =useUser()// 将store中的状态解构出来const{ name, age, height }=storeToRefs(userStore)</script>

🍟state其他操作

读取和写入 state

默认情况下,您可以通过 store 实例访问状态来直接读取, 刚刚我们就是这样读取状态的

写入状态其实也同理, 通过store实例访问状态直接修改

<template><divclass="home"><!-- 展示userStore中的状态 --><h2>{{ name }}</h2><h2>{{ age }}</h2><h2>{{ height }}</h2><button@click="changeInfo">修改信息</button></div></template><scriptsetup>import{ storeToRefs }from'pinia';import useUser from"../stores/user"const userStore =useUser()const{ name, age, height }=storeToRefs(userStore)functionchangeInfo(){// 使用实例访问状态, 进行修改
    userStore.name ="王老五"
    userStore.age =20
    userStore.height =1.89}</script>

重置 State

当我们对某些状态进行了修改之后, 我们可以通过调用 store 上的 $reset() 方法将状态

重置到其初始值

$reset()方法会将所有的状态重置到初始值

<template><divclass="home"><!-- 展示userStore中的状态 --><h2>{{ name }}</h2><h2>{{ age }}</h2><h2>{{ height }}</h2><button@click="changeInfo">修改信息</button><button@click="resetInfo">重置信息</button></div></template><scriptsetup>import{ storeToRefs }from'pinia';import useUser from"../stores/user"const userStore =useUser()const{ name, age, height }=storeToRefs(userStore)functionchangeInfo(){
    userStore.name ="王老五"
    userStore.age =20
    userStore.height =1.89}functionresetInfo(){// 重置状态
    userStore.$reset()}</script>

同时修改多个状态

可以调用 $patch 方法 , 它允许您使用部分“state”对象同时应用多个更改;

<template><divclass="home"><!-- 展示userStore中的状态 --><h2>{{ name }}</h2><h2>{{ age }}</h2><h2>{{ height }}</h2><button@click="changeInfo">修改信息</button></div></template><scriptsetup>import{ storeToRefs }from'pinia';import useUser from"../stores/user"const userStore =useUser()const{ name, age, height }=storeToRefs(userStore)functionchangeInfo(){// $patch一次性修改多个状态
    userStore.$patch({name:"罗三炮",age:50,height:1.58})}</script>

Pinia核心Getters

🍕getters基本使用

Getters相当于Store的计算属性

它们可以用 defineStore() 中的 getters 属性定义;

getters中可以定义接受一个state作为参数的函数;

  • 在defineStore中定义getters
import{ defineStore }from"pinia"const useCounter =defineStore("counter",{state:()=>({counter:101}),// 定义gettersgetters:{doubleCounter(state){return state.counter *2}}})exportdefault useCounter
  • 直接通过store对象就可以访问当前store的Getters
<template><!-- 访问当前store的Getters --><h2>{{ counterStore.doubleCounter }}</h2></template><scriptsetup>import useCounter from"../stores/counter"const counterStore =useCounter()</script>

🍕getters其他操作

Getters中访问自己的其他Getters

我们可以通过

this来访问到当前store实例的所有其他属性

;

this相当于是绑定的store实例

  • 例如在getter中访问自己的doubleCounter
getters:{doubleCounter(state){return state.counter *2},doubleCounterAddOne(){returnthis.doubleCounter +1}}

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

const useCounter =defineStore("counter",{state:()=>({counter:101,friend:[{id:111,name:"chenyq"},{id:112,name:"王老五"},{id:113,name:"罗三炮"},]}),getters:{// getter可以返回一个函数getfriendById(){return(id)=>{returnthis.friend.find(item=> item.id == id)}}}})
<h2>{{ counterStore.getfriendById(111) }}</h2><h2>{{ counterStore.getfriendById(112) }}</h2>

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

// 导入usrUserimport useUser from"./user"const useCounter =defineStore("counter",{state:()=>({counter:101}),getters:{showMessage(state){// 拿到userStore对象, 获取userStore中的信息const userStore =useUser()// 返回自己store的信息拼接上userStore中的信息return`${state.counter}${userStore.name}`}}})
<h2>{{ counterStore.showMessage }}</h2>

Pinia核心Actions

🥧Actions基本使用

Actions 相当于组件中的 methods

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

和getters一样,在action中可以通过

this访问整个store实例的所有操作

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()functionchangeState(){// 通过store实例调用即可
    counterStore.increment()}</script>

🥧Actions异步操作

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

例如在Actions发生网络请求

import{ defineStore }from'pinia'const useHome =defineStore("home",{state:()=>({// 定义空数组用于接收网络请求数据banners:[],recommends:[]}),actions:{// 支持异步操作asyncfetchHomeMultidata(){// 发送网络请求获取数据const res =awaitfetch("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
    }}})exportdefault useHome

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

<template><divclass="about"><ulv-for="item in homeStore.banners":key="item.acm"><li>{{ item.title }}</li></ul></div></template><scriptsetup>import useHome from"../stores/home"const homeStore =useHome()// 告知发送网络请求
  homeStore.fetchHomeMultidata()</script>

本文转载自: https://blog.csdn.net/m0_71485750/article/details/125982691
版权归原作者 学全栈的灌汤包 所有, 如有侵权,请联系我们删除。

“Vue中的Pinia状态管理工具 | 一篇文章教会你全部使用细节”的评论:

还没有评论