深入浅出 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,并且可以手动修改调试数据。

相关推荐
摸鱼的春哥12 小时前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
念念不忘 必有回响12 小时前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
C澒12 小时前
多场景多角色前端架构方案:基于页面协议化与模块标准化的通用能力沉淀
前端·架构·系统架构·前端框架
崔庆才丨静觅12 小时前
稳定好用的 ADSL 拨号代理,就这家了!
前端
江湖有缘12 小时前
Docker部署music-tag-web音乐标签编辑器
前端·docker·编辑器
恋猫de小郭13 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅20 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606121 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了21 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅21 小时前
实用免费的 Short URL 短链接 API 对接说明
前端