卡比记账项目——全局状态管理工具Pinia

127 阅读4分钟

前置知识

一个组件,外部的数据放在props里面内部的数据可以放在ref/reactive里。

截屏2022-12-02 12.30.28.png 两个组件情况会比较复杂。

第一种情况:父子关系

子组件会通过props来获得父组件的一些属性,这个子组件也拥有自己的ref/reactive

截屏2022-12-02 12.32.18.png

假设现在有一个数据叫做currentUser,很多组件都需要用到这个数据。如何实现呢。 我们很容易想到:父组件向服务器请求currentUser,放到ref里面,子组件也去请求currentUser也放到自己的ref了里面。从逻辑上是没有任何问题的。 但是这样会造成一些后果:

  1. 请求太多了
  2. 数据冗余 所以基本不使用这种办法,我们选择的思路是复用 实现办法:让父组件向服务器请求currentUser,拿到数据后放在自己的ref/reactive里面。父组件可以对其进行读和写的操作。子组件可以通过props来得到这个数据,但是是只读的,如果想修改只能context.emit('update:currentUser,user2)这种形式。把user2赋值到currentUser上。
第二种情况:爷孙关系

中间隔了一代,不能直接通过props实现爷组件向孙组件的数据通信,只能先传输给父组件再传给孙组件。很显然这样做是不好的。

所以在Vue中跨组件通信需要依赖注入 在爷组件处进行provide,在孙组件处进行inject。

第三种情况:兄弟关系

有两个并列关系的兄弟组件,都需要用到currentUser数据。这种情况,按照常规思路就是借助他们两个组件的父组件先请求currentUser然后分别通过props给这两个兄弟组件。

第四种情况:远方亲戚关系

截屏2022-12-02 12.49.46.png 实现1和2两个组件读取currentUser,依然是依赖注入方法。 在parent组件中进行provide,随后在1组件和2组件进行inject即可。

以上思路也是Vue和React的通用思路。

Vue专属思路

截屏2022-12-02 12.53.38.png

假设组件是如图所示的树形,如果想实现任意两个组件共享变量都是很容易的。假设他们都需要用到me这个数据,只需要将其命名为me.js然后

export const me = ref({name:xxx,id:yyy})

在需要使用me的组件中 import {me}即可。都可以对me进行读写。

所以对于任何需要共用的属性,可以导出一个全局的store

export cosnt store = reactive({
me:{},
tags:{},
})

任何组件想用store直接import即可。

全局状态管理工具——Pinia

为什么使用Pinia

Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。 如果您熟悉 Composition API,您可能会认为您已经可以通过一个简单的 export const state = reactive({}). 这对于单页应用程序来说是正确的,但如果它是服务器端呈现的,会使您的应用程序暴露于安全漏洞。 但即使在小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:

  • dev-tools 支持
-   跟踪动作、突变的时间线
-   Store 出现在使用它们的组件中
-   time travel 和 更容易的调试
  • 热模块更换
-   在不重新加载页面的情况下修改您的 Store
-   在开发时保持任何现有状态
  • 插件:使用插件扩展 Pinia 功能
  • 为 JS 用户提供适当的 TypeScript 支持或 autocompletion
  • 服务器端渲染支持

Pinia解决了跨请求状态污染的问题

使用Pinia

定义Store的方法,声明的store必须以use开头

const useStore = =defineStore('store',{
state(){
   return {
   //存放数据
     me:{
     name:Origami
     }
   }
},
actions:{
//操作
refrtchMe(){
   this.me.name = 'xxx'
   ajax().then(()=>{
   this.me
   })
}
}
})

在此之前要先配置App

截屏2022-12-02 14.19.10.png

封装useMeStore

使用Pinia封装一个存放me的store代替之前的me.tsx

截屏2022-12-02 15.10.15.png 然后在用到me的地方进行替换即可。

使用storeToRefs

为了解构赋值可以使用storeToRefs 解构之后的东西就是响应式的。

截屏2022-12-02 15.19.42.png

封装useItemStore

ItemSummary组件中里面的数据都是用ref作为容器。由此我们可以封装一个useItemStore。

state放置数据

截屏2022-12-02 15.54.46.png

actions放置方法:

截屏2022-12-02 16.12.32.png 在ItemSummary中引入,并修改对应的变量名。

Pinia的ID固定——共享数据 Pinia的ID不固定——如果相等就共享,反之亦然