Pinia 实践 | 青训营笔记

什么是Pinia

如果你学过Vue2,那么你一定使用过Vuex。我们都知道Vuex在Vue2中主要充当状态管理的角色,所谓状态管理,简单来说就是一个存储数据的地方,存放在Vuex中的数据在各个组件中都能访问到,它是Vue生态中重要的组成部分。

既然Vuex那么重要,那么在Vue3中岂能丢弃! 在Vue3中,可以使用传统的Vuex来实现状态管理,也可以使用最新的pinia来实现状态管理,我们来看看官网如何解释pinia的。

官网解释:

Pinia是 Vue的存储库,它允许您跨组件/页面共享状态。

从上面官网的解释不难看出,pinia和Vuex的作用是一样的,它也充当的是一个存储数据的作用,存储在pinia的数据允许我们在各个组件中使用。

实际上,pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名pinia,而没有取名Vuex,所以大家可以直接将pinia比作为Vue3的Vuex

为什么使用Pinia

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

使用Pinia

安装pinia

npm install pinia

核心概念

  • store:状态仓库
  • state:状态,和 vuex 保持一致
  • getters:类似组件的计算属性,和 vuex 中的 getters 的保持一致
  • actions:和 vuex 中的 actions 保持一致,可以处理逻辑并修改 state

使用步骤

  1. 创建 pinia
  2. 注册 pinia
  3. 创建 store
  4. 抽离需要管理的数据作为 state,声明 getters 优化状态读取,声明 actions 处理业务逻辑
  5. 在需要的地方(组件或其他),导入和使用 store

创建 pinia

在store/index.ts文件中创建并返回pinia实例

ts 复制代码
//引入创建pinia的方法
import { createPinia } from "pinia";
//创建并返回pinia实例
const pinia = createPinia();

export default pinia;

注册 pinia

在mian.ts文件中注册pinia

ts 复制代码
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import pinia from './store'

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

创建 store

使用 defineStore 方法创建 storestore 的命名遵循 useXXX 的形式。创建时需要指定一个唯一的 id

在store/user.ts文件中创建store

ts 复制代码
//引入定义store的方法
import { defineStore } from 'pinia'

/**
 * 第一个参数是store的唯一id,或者说是模块
 * 第二个参数是一个对象,store的配置项,比如store内的数据
 */
export const useUserStore = defineStore("user", {})

state getters actions

在store/user.ts文件中使用state getters actions

ts 复制代码
export const useUserStore = defineStore("user", {
  /**
   * 定义当前模块的state
   * state是一个函数,必须有返回值,返回值即这个模块的状态
   * pinia可以完整的推断出state的类型
   * @returns 
   */
  state() {
    return {
      /**年龄 */
      age: 18,
      name: '张三',
    }
  },

  getters: {
    /**
     * 当前年龄的两倍
     * 接收一个参数 ------------ 当前模块的state
     * 必须有返回值,返回值就是这个计算属性的结果
     * @param state 
     * @returns 
     */
    doubleAge: (state) => state.age * 2,

    /**
     * 在getter中调用其他的计算属性方法
     * 不能使用箭头函数的形式
     * 
     * 此处,this关键字指向的是store实例
     * 
     * 还需要自定义函数的返回值类型
     * @returns 
     */
    getNameAndAge() : string {
      return this.name + this.age;
    },

    /**
     * 接收页面上传过来的参数
     * 计算属性内部返回一个方法,方法接收一个参数,这个参数就是页面传过来的参数
     * @returns 
     */
    getAddAge() {
      return (num: number) => this.age + num;
    }
  },

  /*
      当前模块的相关方法
      存放当前模块的相关的业务逻辑函数
   */
  actions: {
    /**
     * 在pinia中,可以直接通过actions修改state
     * pinia中的actions既可以是异步的又可以是同步的
     * @param name 
     */
    saveName(name: string) {
      this.name = name;
    }
  }
})

使用store

state里面的数据是响应式的

在App.vue文件中

ts 复制代码
<template>
  <div>
    你好,我是pinia,年龄{{ userStore.age }}
  </div>
  <div>
    <button @click="add">加一</button>
  </div>
  <div>
    计算属性--{{ userStore.doubleAge }}--{{ userStore.getNameAndAge }}
  </div>
  <div>
    计算属性--{{ userStore.getAddAge(11) }}
  </div>
  <div>
    {{ userStore.name }}
    <button @click="changeName">修改名字</button>
  </div>
</template>

<script setup lang="ts">
import { useUserStore } from './store/user'

const userStore = useUserStore();

/**
 * 可以直接操作store中的状态并且重新渲染
 * 也就是说state里面的数据是响应式的
 */
const add = () => {
  userStore.age++;
}

const changeName = () => {
  userStore.saveName('李四');
}
</script>

pinia 持久化

Pinia 的数据是存在内存当中的,页面刷新数据就会丢失。所以对于一些重要数据,需要持久化到本地存储,简单的数据可以直接调用 localStorage 或者 sessionStorage。更推荐的是使用持久化插件,比如 pinia-plugin-persistedstate

在store/index.ts中引入持久化插件

ts 复制代码
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

pinia.use(piniaPluginPersistedstate)

Pinia 中的状态是以 store 为单位进行管理的。哪个 store 中的数据需要持久化,就在哪个 store 中去开启。比如:

在store/user.ts文件中开启持久化

ts 复制代码
const useUserStore = defineStore('user', {
    persist: true,
    // ...... 
})
相关推荐
CallBack8 个月前
Typora+PicGo+阿里云OSS搭建个人图床,纵享丝滑!
前端·青训营笔记
Taonce1 年前
站在Android开发者的角度认识MQTT - 源码篇
android·青训营笔记
AB_IN1 年前
打开抖音会发生什么 | 青训营
青训营笔记
monster1231 年前
结营感受(go) | 青训营
青训营笔记
翼同学1 年前
实践记录:使用Bcrypt进行密码安全性保护和验证 | 青训营
青训营笔记
hu1hu_1 年前
Git 的正确使用姿势与最佳实践(1) | 青训营
青训营笔记
星曈1 年前
详解前端框架中的设计模式 | 青训营
青训营笔记
tuxiaobei1 年前
文件上传漏洞 Upload-lab 实践(中)| 青训营
青训营笔记
yibao1 年前
高质量编程与性能调优实战 | 青训营
青训营笔记
小金先生SG1 年前
阿里云对象存储OSS使用| 青训营
青训营笔记