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 中查看。

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

相关推荐
山川尔尔_12 分钟前
JS手写-this绑定实现
开发语言·javascript·ecmascript
那就可爱多一点点1 小时前
H5页面多个视频如何只同时播放一个?
前端·音视频
谁呛我名字3 小时前
大数据应用开发——数据可视化
javascript·vue.js·echarts
前端郭德纲3 小时前
浅谈React的虚拟DOM
前端·javascript·react.js
2401_879103684 小时前
24.11.10 css
前端·css
ComPDFKit5 小时前
使用 PDF API 合并 PDF 文件
前端·javascript·macos
yqcoder5 小时前
react 中 memo 模块作用
前端·javascript·react.js
谈谈叭6 小时前
Javascript中的深浅拷贝以及实现方法
开发语言·javascript·ecmascript
优雅永不过时·6 小时前
Three.js 原生 实现 react-three-fiber drei 的 磨砂反射的效果
前端·javascript·react.js·webgl·threejs·three
爱编程的鱼7 小时前
javascript用来干嘛的?赋予网站灵魂的语言
开发语言·javascript·ecmascript