Pinia的基本使用

在Vue3中,可以使用传统的Vuex来实现状态管理,也可以使用最新的Pinia来实现状态管理,我们来看看官网如何解释Pinia的:Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态。从官网的解释不难看出,Pinia和Vuex的作用其实是一样的,它也充当的是一个存储数据的作用,存储在Pinia的数据允许我们在各个组件中使用。实际上,Pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名Pinia,而没有取名Vuex,所以大家可以直接将Pinia比作为Vue3的Vuex。

为什么使用Pinia


很多小伙伴可能会抛出一系列的疑问:为什么要学习Pinia?Pinia有什么优点吗?既然Vue3还能使用Vuex为什么我还要学它?

这些问题其实都有答案,我们不可能平白无故的而去学习一样东西吧!肯定它有自己的优点的,所以这里我们先列出Pinia的优点:

  • Vue2和Vue3都支持。
  • Pinia中只有state、getters、actions,抛弃了Vuex中的Mutation,Vuex中mutation一直都不太受小伙伴们的待见,Pinia直接抛弃它了,这无疑减少了我们工作量。
  • Pinia中actions支持同步和异步,Vuex不支持。
  • 良好的Typescript支持,我们知道Vue3都推荐使用TS来编写,这个时候使用Pinia就非常合适了。
  • 无需再创建各个模块嵌套了,Vuex中如果数据过多,我们通常分模块来进行管理,稍显麻烦,而Pinia中每个store都是独立的,互相不影响。
  • 体积非常小,只有1KB左右。
  • Pinia支持插件来扩展自身功能。
  • 支持服务端渲染。

 

Pina的基础特性:

State

  • 默认情况下,通过 store 实例访问 state,可以直接读取和写入,如 @click=“store.count++”。
  • 通过 store.$reset() 方法可以将 state 重置为初始值。
  • 除了直接通过 store 修改 state,还可以通过 store.$patch() 方法提交多个更改。

Getters

  • Getters 属性的值是一个函数,接受 state 作为第一个参数,目的是鼓励使用箭头函数。
  • 非箭头函数会绑定 this,建议仅在需要获取整个 store 实例的场景使用,且需要显式定义函数返回类型。

Actions

  • 与 Gettes 一样可以通过 this 访问整个 store 实例。
  • Actions 可以是异步的或同步的,不管怎样,都会返回一个 Promise。
  • Actions 可以自由的设置参数和返回的内容,一切将自动推断,不需要定义TS 类型。

 

Pinia的基本使用

  1. 创建一个项目,安装pinia
  2. 创建store以及使用store
  3. 添加state以及操作state
  4. getters属性
  5. actions属性

因为Pinia基本都是基于Vue3使用,至于Vue2中如何使用,这里就不讲解了,可以自行去Pinia官网学习,毕竟Vue2中使用pinia的还是少数。
地址:https://pinia.vuejs.org/

 

 

1.1.创建一个最新的Vue3 + TS + Vite项目

 执行命令:npm create vite@latest pinia-vite-demo --template vue-ts

1.2.运行项目:

执行命令:npm install
然后npm run dev

1.3.安装pinia:

执行命令:yarn add pinia 或者使用npm npm install pinia

 

1.4.安装完成后我们需要将 pinia 挂到 vue 应用中

     也就是我们需要创建一个根存储传递给应用程序,简单来说就是创建一个存储数据的数据桶,放到应用程序中去。需要修改main.ts/js文件,引入pinia提供的createPinia方法,创建根存储。

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
//引入pinia提供的createPinia方法,创建根存储
import {createPinia} from 'pinia'
const pinia = createPinia();
const app = createApp(App);
app.use(pinia)
app.mount('#app')

2.1.创建store,那什么是store呢?

      (官网解释)一个 Store (如 Pinia)是一个实体,它持有未绑定到您的组件树的状态和业务逻辑。换句话说,它托管全局状态。它有点像一个始终存在并且每个人都可以读取和写入的组件。它有三个概念,state、getters 和 actions 并且可以安全地假设这些概念等同于组件中的“数据”、“计算”和“方法”。

 

      我们可以把这三个概念理解为vue组件中的“数据”data、“计算”computed和“方法”methods。store简单来说就是数据仓库的意思,我们数据都放在store里面。我们也可以把它理解为一个公共的组件,只不过该公共组件只存放数据,这些数据我们其它所有的组件都能够访问且可以修改。

      我们需要使用pinia提供的defineStore()方法来创建一个store,该store用来存放我们需要全局使用的数据。首先在项目src目录下新建store文件夹,用来存放我们创建的各种store,然后在该目录下新建xxx.ts文件,主要用来存放与xxx相关的store,不同的store用来存放不同的全局数据,相当于把它们进行了分类,方便我们更好的管理。一旦 store 被实例化,你就可以直接在 store 上访问 state、getters 和 actions 中定义的任何属性。

      比如有一个用户相关的数据,我们可以在store目录下创建一个user.ts,还有一个产品相关的数据,再创建一个product.ts,这两个没有关联的数据,我们可以分别给他们创建一个store来管理,代码如下:

//创娃store很简单,调用pinia中的definestore函数即可,该函数族收两个参数:
import {defineStore} from 'pinia'

//第一个参敬是应用程序中store的唯一id,就是给数据仓库起个名字
//第二个参数是一个对象,store的配置项,比如配置store内的数据,修改数据的方法等等
export const useUsersStore = defineStore('user',{
    //其他配置项

})

2.2.使用store

假如我们要在App.vue里面使用它,使用 store 很简单,直接引入我们声明的 useUsersStore 方法即可,我们可以先看一下执行方法输出的是什么:

<script setup lang="ts">
  import { useUsersStore } from './store/user';
  const store = useUsersStore();
  console.log(store)
</script>

3.1.添加state

      我们都知道store是用来存放公共数据的,我们利用defineStore函数创建了一个store,该函数第二个参数是一个options配置项,我们需要存放的数据就放在options对象中的state属性内。该属性就是用来存储数据的,我们往state中添加了3条数据。需要注意的是,state接收的是一个箭头函数返回的值,它不能直接接收一个对象。

import {defineStore} from 'pinia'
export const useUsersStore = defineStore('user',{
     //这里的state与vue2中用来存放初始化变量的data的写法相似,需要return
    state:()=>{
        return {
            name:"不知好歹",
            age:20,
            sex:"女",
            items:[80,90]
        }
    },
})

3.2.操作state

3.2.1.读取state数据

我们往store里面存储数据就是为了操作它。首先我们读取一下它的数据,并让它在页面上显示,我们直接通过store.xxx的方式获取到了store存储的值,但是,这样比较繁琐,我们可以用解构的方式来获取值,使得代码更简洁一点。代码如下:

<template>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <p>性别:{{ sex }}</p>
</template>
<script setup lang="ts">

  import { useUsersStore } from './store/user';
  import {storeToRefs} from 'pinia'//响应式改变数据状态
  const store = useUsersStore();
  const {name,age,sex,items} = storeToRefs(store);
  
 </script>

image

 

3.2.2. 多个组件使用state数据

我们使用store最重要的目的就是为了组件之间共享数据,那么接下来我们新建一个child.vue组件,在该组件内也使用state数据,跟App.vue几乎一样,代码如下:

<template>
    <h1>我是Child组件</h1>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <p>性别:{{ sex }}</p>
</template>
<script setup lang="ts">

  import { useUsersStore } from './store/user';
  import {storeToRefs} from 'pinia'//响应式改变数据状态
  const store = useUsersStore();
  const {name,age,sex,items} = storeToRefs(store);
  
 </script>

image

 3.2.3. 修改、重置、批量修改以及替换state数据

      想要修改store中的数据,可以直接重新赋值即可,重置只要调用store.$reset() 方法即可,而批量修改也有更简便的方法,使用store的patch()方法就行了,patch()有两种用法:①只传需要修改的数据就可以了,②可以使用patch的函数参数用法, 最后就是替换整个state,store.state(用的较少),利用pinia的storeToRefs函数,就可以将state中的数据变成响应式的,代码如下:

<template>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <p>性别:{{ sex }}</p>
    <button @click="changeName">更改姓名</button>
    <button @click="reset">重置state</button>
    <button @click="patchStore">批量修改</button>
    <button @click="thstore">替换store</button>
    <!-- <child></child> -->
</template>
<script setup lang="ts">
  // import child from './child.vue'
  import { useUsersStore } from './store/user';
  import {storeToRefs} from 'pinia'
  const store = useUsersStore();
  const {name,age,sex,items} = storeToRefs(store);
   //更改state数据
   const changeName = () =>{
      store.name = "张三";
      console.log(store)
   }
   //重置state
   const reset =()=>{
    store.$reset();
   }
   //批量修改store,传想要更改的数据就可以
   const patchStore = () =>{
      //普通用法
      // store.$patch({
      //   name:"呜小游",
      //   age:27,
      // })
      //函数用法
      store.$patch((state)=>{
        state.name = '鹿小优'
        state.items.push(100)
      })
    }
    //替换state
    const thstore = () => {
      store.$state = {
        name:"艾斯",
        age:36,
        sex:"男",
        items:[666]
      };
    };

</script>

4.1.getters属性

 getters是defineStore参数配置项里面的另一个属性,getter属性值是一个对象,该对象里面是各种各样的方法,跟Vue中的计算属性类似,它的作用就是返回一个新的结果。当然我们这里的getter就是处理state数据。

4.2.添加getter

 我们在配置项参数中添加getter属性,我们在该属性对象中定义一个getAddAge方法,该方法会默认接收一个state参数,也就是state对象,然后该方法返回的是一个新的数据。代码如下:

 

import {defineStore} from 'pinia'
export const useUsersStore = defineStore('user',{
     //这里的state与vue2中用来存放初始化变量的data的写法相似,需要return
    state:()=>{
        return {
            name:"不知好歹",
            age:20,
            sex:"女",
            items:[80,90]
        }
    },
    getters:{
        getAddAge:(state) =>{
            return state.age + 80;
        },
    },
})

4.3. 使用getter

 可以直接在标签上使用了store.gettAddAge方法,这样可以保证响应式,当我们点击修改数据按钮时,页面上的新的年龄字段也会跟着变化。代码如下:

image

 

image

 

4.4.getter中调用其它getter

我们再定义了一个名为getNameAndAge的getter函数,我们这里不使用箭头函数的形式,因为我们想在函数内部使用this,箭头函数的this指向问题相信大家都知道吧!所以这里没有采用箭头函数的形式。而是在函数内部直接使用this来获取state数据以及调用其它getter函数,这里this指向的是store实例,所以我们可以直接在getter方法中调用this。代码如下:

image

 

4.5.getter传参

既然getter函数做了一些计算或者处理,那么我们很可能会需要传递参数给getter函数,但是我们前面说getter函数就相当于store的计算属性,和vue的计算属性差不多,我们都知道Vue中计算属性是不能直接传递参数的,所以我们这里的getter函数如果要接受参数的话,也是需要做处理的。

image

 

5.1.actions属性

 

 

 

 

 

 

 

 

 

 

 

 

转: https://blog.csdn.net/qq_44505797/article/details/130407908

 

posted @ 2025-07-28 16:26  与f  阅读(105)  评论(0)    收藏  举报