【vue3生态Pinia之State、Getters、Actions详解】

44 篇文章 6 订阅

本章节请配合`Pinia快速上手章节`该文章食用,下列内容会结合该文章内的例子进行讲解,标红部分表示该文章内容

没基础的,请先看上一篇Pinia文章,这样对这篇的内容会更方便理解。

前情提要:

  1. 不讲多store互相使用(看上个文章);
  2. 如果有些你觉得我讲了你看不懂,请先看上一篇文章,太基础的或上一篇已有的这里则会没讲!

# State

大多数时候,`state` 是一个 Store 的主要部分。通常从定义 state 开始,代表vue实例的Store应用。
1. 定义、使用 state 见上一篇文章
2. 重置state数据:
  您可以通过调用 store 上的方法将状态重置为其初始值:$reset()
  const store = useStore()
  store.$reset()
3. 修改state数据:
  store.property = xxxx
  store.$patch({}) // 或者这样,这种可以统一多个修改
  store.$patch((state)=>{ /** 这里修改state */ }) // $patch 方法还接受一个函数,用于应对复杂数据的修改过程
4. 更换state:
  $state您可以通过将商店的属性设置为新对象来替换Store的整个状态:
  store.$state = { counter: 666, name: 'Paimon' }
5. 订阅state:
  store.$subscribe((mutation, state) => {
    // import { MutationType } from 'pinia'
    mutation.type // 'direct' | 'patch object' | 'patch function'
    // same as cartStore.$id > store 的 name
    mutation.storeId // 'cart'
    // only available with mutation.type === 'patch object'
    mutation.payload // patch object passed to cartStore.$patch()
    // 无论何时更改,都将整个状态保留到本地存储  >  persist the whole state to the local storage whenever it changes
    localStorage.setItem('cart', JSON.stringify(state))
  },{ detached: false })
  // detached 默认是false,表示当组件被卸载时,$subscribe 订阅将被自动删除。
  // 如果要在组件卸载后保留 $subscribe 订阅,则改为 true 以从当前组件中分离状态订阅:


# Getters

声明、使用的案例见3. 4.
1- Getter 完全等同于Store里的state的computed值。
2- 他们接收state作为第一个参数,鼓励使用箭头函数功能:
3- 外部(组件)将参数传递给 getter  >>> 见下面代码的 getUserById
4- 访问其他store的getters

export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  getters: {
    // 类型是自动推断的,因为我们没有使用 this  >> type is automatically inferred because we are not using `this`
    // 自动将返回类型推断为number >> automatically infers the return type as a number
    doubleCount(state) {
      return state.counter * 2
    },
    // 必须显式设置返回的数据类型
    doublePlusOne(): number {
      // 整个store的自动完成和typings(不知道咋翻译)  >>  autocompletion and typings for the whole store ✨
      return this.counter * 2 + 1
      
      // 与计算属性一样,您可以组合多个 getter。通过 this 访问任何其他 getter
      // return this.doubleCount * 2 + 1
    },
    getUserById: (state) => {
      // Getter只是在幕后计算的属性,因此不可能将任何参数传递给它们。但是,您可以从getter返回一个函数以接受任何参数:
      // 请注意,执行此操作时,getter 不再缓存,它们只是您调用的函数。但是,您可以在 getter 本身内部缓存一些结果,这并不常见,但应该证明性能更高: 这段话的功能,要用再去参考官网
      return (userId) => state.users.find((user) => user.id === userId)
    },
    // 要使用其他store 的 getter,您可以直接在getter内部使用它:
    otherGetter(state) {
      const otherStore = useOtherStore()
      return state.localData + otherStore.data
    },
  },
})

上面的功能3演示

<template>
  <p>User 2: {{ getUserById(2) }}</p>
</template>

<script>
export default {
  setup() {
    const store = useStore()
    store.counter = 3
    console.log(store.doubleCount) // 6  >> 跟state一样,可直接访问。
    return {
      getUserById: store.getUserById
    }
  },
}
</script>

# Actions

Actions 相当于组件中的 methods。
1- 你也可以完全自由地设置你想要的任何参数并返回任何东西。调用actions时,一切都会自动推断!
2- 访问其他store的actions等内容;
3- 订阅actions;
  传递给订阅的回调比actions事件先一步执行。
  默认情况下,actions订阅绑定到添加它们的组件(如果Store位于组件内部setup()里)。意思是,当组件被卸载时,它们将被自动删除。如果要在卸载组件后保留它们,传入第二个参数 true 用以将actions订阅与当前组件分离。

import { useAuthStore } from './auth-store'
export const useSettingsStore = defineStore('settings', {
  state: () => ({
    // ...
  }),
  actions: {
    fetchUserPreferences(preferences) {
      const auth = useAuthStore() 
      console.log(auth)
    },
  },
})

订阅actions

export default {
  setup() {
    const someStore = useSomeStore()

    const unsubscribe = someStore.$onAction(
      ({
        name, // name of the action
        store, // store instance, same as `someStore`
        args, // array of parameters passed to the action
        after, // hook after the action returns or resolves
        onError, // hook if the action throws or rejects
      }) => {
        // a shared variable for this specific action call
        const startTime = Date.now()
        // this will trigger before an action on `store` is executed
        console.log(`Start "${name}" with params [${args.join(', ')}].`)

        // this will trigger if the action succeeds and after it has fully run.
        // it waits for any returned promised
        after((result) => {
          console.log(
            `Finished "${name}" after ${
              Date.now() - startTime
            }ms.\nResult: ${result}.`
          )
        })

        // this will trigger if the action throws or returns a promise that rejects
        onError((error) => {
          console.warn(
            `Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
          )
        })
      }
    )

    // 可手动销毁订阅 manually remove the listener
    unsubscribe()
    // ...
  },
}

Pinia是刚学几小时,相关例子不是特别丰富,但功能还是表述出来了和简单的写了。自己也多动手敲!!

Pinia 进阶的 Plugins 后续会再写一篇文章进行讲解。


QQ交流群:522976012  ,欢迎来玩。

聚焦vue3,但不限于vue,任何前端问题,究其本质,值得讨论,研究与学习。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值