Pinia 在企业级项目中的最佳实践

前言

Pinia,作为Vue官方团队新推荐的数据管理器,采用了Composition API设计,为开发者提供了更为轻松的上手体验,同时保留了许多优秀的特性。

在本文中,我们将不深入介绍具体的使用方法,而是重点分享如何在项目中更有效地运用和管理Pinia store。这里的实践经验主要来源于 Ray Template

通过采用Pinia,你可以体验到更简洁而强大的状态管理,其设计理念不仅减轻了学习负担,还为你提供了更丰富的特性。如果你希望更深入地了解如何在项目中最大程度地发挥Pinia的优势,请参考 Ray Template

起步

在企业级项目中,模块的良好维护至关重要,特别是对于store仓库,以下几个方面是需要考虑的关键点:

  1. 模块化组织:store拆分为逻辑相关的模块,以提高可维护性和可扩展性。每个模块应专注于一个明确的功能领域,避免功能耦合。

  2. 命名空间: 使用命名空间来避免命名冲突,确保模块在全局命名空间中是唯一的。这样可以有效防止不同模块之间的状态或操作互相影响。

  3. 文件结构: 组织清晰的文件结构对于长期维护至关重要。可以按照模块来组织文件,也可以按照功能来组织。在项目结构清晰的基础上,寻找和修改代码将更加轻松。

  4. 持久化: 对于需要持久化的状态,考虑使用合适的方案,例如将状态存储在本地存储或会话存储中。这有助于在刷新页面或重新加载应用时保持状态。

通过关注这些方面,可以更好地组织和维护store仓库,使其更符合企业级项目的需求。

规划模块

一般来说,会在 src 目录下创建一个 store 文件夹,当作项目的数据仓库。

css 复制代码
├── src
│   ├── store

目前的项目结构如上。

命名空间

在使用 piniadefineStore 进行仓库初始化时,有一些关键点需要特别注意:

  1. 关注 key 的唯一性: defineStore 方法中的 key 应该是唯一的,以确保在整个应用中不会出现冲突。这有助于pinia正确识别和管理不同的仓库。

  2. 不支持 symbol 类型: defineStore 不支持使用 symbol 类型作为仓库的 key,因为它要求 key 必须是一个字符串。如果使用 symbol,将收到 TypeScript 的类型报错。

通过确保 key 的唯一性和避免使用 symbol,可以更好地使用 piniadefineStore 方法初始化仓库,并有效地避免潜在的问题。

文件结构

一个良好的文件结构规划对于阅读和管理 pinia 仓库至关重要。以下是一个推荐的文件结构管理方式:

go 复制代码
├── store
│   ├── hooks
│   │   ├── useUserStore.ts
│   ├── user
│   │   ├── type.ts index.ts helper.ts ...
│   index.ts

在这个结构中:

  • store 文件夹包含了所有的 pinia 仓库模块。
  • 每个模块有一个独立的文件夹,文件夹中包含了 index.tstype.tshelper.ts 等文件,便于分别管理不同的模块功能。
  • index.ts 文件用于导出该模块的 store 实例。

这种结构有助于保持代码的整洁性,提高可读性,便于模块的维护和扩展。在 index.ts 中导入仓库模块,从而在应用中使用。

pinia 持久化

pinia-plugin-persistedstate 插件是一个方便的插件,允许你为每个仓库模块进行单独的持久化状态配置。它的使用方式简便,具体的详细信息可以在插件的 GitHub 页面上查看。

这个插件的主要优点有:

  • 仓库级配置: 你可以为每个仓库模块单独配置是否需要持久化状态。
  • 灵活的配置选项: 提供了灵活的配置选项,可以根据项目的需要进行定制。
  • 简化持久化逻辑: 避免了手动处理本地存储的逻辑,使持久化状态的管理更为简便。

使用这个插件可以很好地管理和保持仓库状态的持久性,确保用户在刷新页面或重新打开应用时能够保留其状态。

理论存在,上手代码

假设我们需要维护一个 user store 模块。

type.ts 类型

ts 复制代码
export interface UserState {
  name: string
  age: number
  address: string
}

index.ts user 仓库模块

ts 复制代码
import type { UserState } from './type'

export const piniaUserStore = defineStore(
  'demo',
  () => {
    const userState = ref<UserState | null>(null)

    const setUserState = (user: UserState) => {
      userState.value = user
    }

    return {
      userState,
      setUserState,
    }
  },
  {
    persist: {
      key: 'piniaUserStore',
      paths: ['userState'],
      storage: sessionStorage | localStorage,
    },
  },
)

hooks/useUserStore getters, actions

这里解释一下为什么不将该代码写在对应的仓库模块下:

  • 这么写更符合 hooks 概念
  • 尽可能避免直接去操作仓库中的逻辑
  • 统一在 hooks 中去维护所有的 getters, acitons
ts 复制代码
import { piniaUserStore } from '../store/user/index'

export const useUserGetters = () => {
  const variable = piniaDemoStore()

  const getUserState = computed(() => variable.userState)

  return {
    getUserState,
  }
}

export const useUserActions = () => {
  const { setUserState } = piniaDemoStore()

  return {
    setUserState,
  }
}

store/index.ts 导出所有仓库模块

ts 复制代码
export { useUserGetters, useUserActions } from './hooks/useUserStore'

页面使用

1s 后页面将会显示最新的 user 信息。

vue 复制代码
<template>
  <ul>
    <li>姓名:{{ getUserState.name }}</li>
    <li>年龄:{{ getUserState.age }}</li>
    <li>地址:{{ getUserState.address }}</li>
  </ul>
</template>
<script setup lang="ts">
import { useUserGetters, useUserActions } from '@/store'

const { getUserState } = useUserGetters() // 获取最新 userState
const { setUserState } = useUserActions() // 获取设置方法

function getUser() {
  setTimeout(() => {
    setUserState({
      name: '章三',
      age: 19,
      address: '中国',
    })
  }, 1000)
}

getUser()
</script>

最后

所有代码可在 Ray Template Store 中查看。

如果对您有所帮助,可以给项目和文章点个赞~~

相关推荐
BUG创建者1 分钟前
openlayers上跟据经纬度画出轨迹
开发语言·javascript·vue·html
IT_陈寒6 分钟前
SpringBoot项目启动速度提升300%?这5个隐藏配置太关键了!
前端·人工智能·后端
小碗细面7 分钟前
5 分钟上手 Claude 自定义 Subagents
前端·人工智能·ai编程
漫随流水8 分钟前
HTML和CSS和JavaScript的区别
javascript·css·html
小J听不清12 分钟前
CSS 浮动(float)全解析:布局 / 文字环绕 / 清除浮动
前端·javascript·css·html·css3
wuhen_n12 分钟前
生产环境极致优化:拆包、图片压缩、Gzip/Brotli 完全指南
前端·javascript·vue.js
用户693717500138418 分钟前
315曝光AI搜索问题:GEO技术靠内容投喂操控答案,新型营销操作全揭秘
android·前端·人工智能
a11177621 分钟前
Three.js 3D模型动画展示项目(开源)
开发语言·javascript·ecmascript
周星星日记24 分钟前
pnpm为什么成为"最先进的管理包工具"
前端
多厘26 分钟前
使用 opencode 和灵感写一个 mac App (实操版)
前端·github