深入浅出 Pinia:革新 Vue 状态管理的利器 ⚡

什么是pinia?

官方解释:Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。

说白了就相当于一个数据储存库,开发者可以将其内部储存的数据应用到各个组件上。pinia对于部分小型项目来说有时候是多此一举,但是对于中大型项目来说是不可或缺的,利用pinia可以很好的解决组件之间状态共享和管理等一系列麻烦。(其前身是Vuex,这里就不过多赘述了)

使用 pinia 的好处

优胜劣汰是自然法则,其同样适用于项目,每个库或工具都有其存在的价值,而pinia也是有一定优点才会被开发者使用。

  • 直观易用的API:pinia提供了state(状态)、getter(计算属性)、action(业务逻辑),抛弃了Vuex中的Mutation。
  • 模块化设计:可以创建多个 store,并且将其分割成不同的模块,有利于大型项目的组织和维护。
  • 轻量级:Pinia 库本身非常轻量,对应用性能影响极小。
  • 良好的 TypeScript 支持:对 TypeScript 的支持非常好,提供了完全类型化的 API。
  • 兼容性好:对于 Vue 3 和 Vue 2 都支持。
  • 插件系统:Pinia 允许开发者扩展其功能。

当然其优点远远不止这些,读者可以在开发时自行体会。

pinia 的基本使用

一、安装 pinia

bash 复制代码
npm install pinia 
# 或者
yarn add pinia

将pinia挂载到Vue上,并且创建一个pinia实例(store 根储存):

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

const app = createApp(App)
const pinia = createPinia();
app
    .use(pinia)
    .mount('#app')

二、创建 store

这里创建 store 其实是创建一个用于集中管理和保存应用全局状态的仓库,并且我们需要 pinia 提供的defineStore()方法来创建一个 store ,其用来存放我们需要全局使用的数据。

具体一般是在 src 文件夹中创建一个 store 文件夹用于存放我们创建的 store,在其目录下就可以新建各种需要的 store 了。例如:创建一个存放user数据的store。

js 复制代码
// src/store/user.js

import { defineStore } from 'pinia'

// 第一个参数是应用程序中 store 的唯一 id
export const useUserStore = defineStore('user', () => {
    // 其他配置...
})

defineStore的第二个参数可以接收两种值:Setup 函数或 Option 对象。

setup 函数

其与 Vue 组合式 API 的 setup 函数 很相似,传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。例如:

js 复制代码
export const useUserStore = defineStore('user', () => {
  const count = ref(0);
  const doubleCount = computed(() => count.value * 2);
  
  function increment() {
    count.value++;
  }

  return { 
      count,
      doubleCount,
      increment,
  }
})
Option 对象

其与 Vue 的选项式 API 类似,传入一个带有 stateactionsgetters 属性的对象。例如:

js 复制代码
export const useUserStore = defineStore('user', {
  // 可以将 state 看作是组件的data选项,返还一个带有你的状态的对象
  state: () => ({ 
      count: 0, 
      name: 'xixili', 
  }),
  
  // getter 是 state 的计算属性,可以衍生出一些状态,并且其接收 state 作为参数
  getters: {
    doubleCount: (state) => state.count * 2
  },
  
  // actions 用来执行状态更改的函数,可以是同步的,也可以是异步的
  actions: {
    increment() {
      this.count++;
    },
  },
})

这两种用法各有各的优势和劣势,挑选自己喜欢的使用即可。


三、使用 store

定义完 store ,接下来就是在需要的组件内调用即可。

html 复制代码
<script setup>
import { useUserStore } from '../store/user.js'
// 这样可以在组件中的任意位置访问 `store` 变量
const userStore = useUserStore();
</script>

实战实例:

安装完并挂载后就可以开始操作了,在 store 文件夹内部创建counter.js

js 复制代码
// counter.js

import { defineStore } from 'pinia'
import { ref } from 'vue'

// 仓库名 函数
export const useCounterStore = defineStore('counter', () => {
    const count = ref(0);

    function increment() {
        count.value++; 
    }
    return {
        count,
        increment,
    }
})

为了体现一个 store 可以在多个组件内同时使用,分别创建CompA.vueCompSubA.vue.

html 复制代码
<!-- CompSubA.vue -->
<template>
    <div>
        CompSubA
        {{ count }}
        <hr>
        {{ counterStore.count }}
    </div>
</template>

<script setup>
import { toRefs } from 'vue';
import { useCounterStore } from '../store/counter';
const counterStore = useCounterStore(); // 本地和中央连接的过程
const { count } = toRefs(counterStore);
// const { count } = counterStore(); 解构
</script>

<style  scoped>

</style>

注: 注释中的解构是没有问题的,但是这样就丢失了响应式,如果还要保持响应式,就需要toRefs方法。

html 复制代码
<!-- CompA.vue -->

<template>
    <div>
        <h2>CompA</h2>
        <p>count: {{ counterStore.count }}</p>
        <button @click="counterStore.increment">Add</button>
        <CompSubA />
    </div>
</template>

<script setup>
import CompSubA from './CompSubA.vue';
// 引入中央模块
import { useCounterStore } from '../store/counter';
const counterStore = useCounterStore();
</script>

<style scoped>

</style>

最后呈现的效果为:

并且其支持开发者工具Vue Devtools,并且可以手动修改调试数据。

相关推荐
2301_773643623 分钟前
ceph镜像
前端·javascript·ceph
程序员黑豆24 分钟前
AI全栈开发之Java:什么是JDK
前端·后端·ai编程
To_OC25 分钟前
万字解析《JS语言精粹》之第四章:函数15大核心精髓(JS灵魂核心)
前端·javascript·代码规范
mqcode35 分钟前
Vue3 + Element Plus + Vite 企业级后台框架搭建全流程
前端
SL-staff37 分钟前
Web 白板技术架构深度解析:从渲染到协作的选型哲学
前端·架构
微扬嘴角40 分钟前
react篇4--setState、LazyLoad和Hooks
前端·javascript·react.js
杨梦馨1 小时前
万级数据表格卡死?Web Worker 一招搞定
前端·javascript·vue.js
阿明在折腾1 小时前
从Canvas到AI模型:我在线工具站里的图片处理实战
前端·后端
CainChen1 小时前
Chrome 远程调试 Android 卡在 Pending authentication 的解决办法
前端
杨运交1 小时前
[030][Web模块]Spring Boot 验证与 OpenAPI 集成实战:从校验规则到文档生成
前端·spring boot·python