Vue3 learning-Pinia state management

Pineapple

Define a Store

import {
    
     defineStore } from 'pinia'
export const useStore = defineStore('main', {
    
    })

This name , also known as id , is necessary and is used by Pinia to connect the store to devtools.

Naming the returned function use... is a convention across composables to make it what you're used to.

use store

import {
    
     useStore } from '@/stores/counter'
const storeObj = useStore()
console.log(storeObj.count)

Once the store is instantiated, you can directly access any properties defined on the store state, gettersandactions

storeis an reactiveobject wrapped with , which means there is no need to write after the getter.value ,

Like setupin props, we cannot destructure it

In order to extract properties from the Store while keeping it responsive, you need to usestoreToRefs()

import {
    
     useStore } from '@/stores/counter'
const {
    
     count } = useStore()
console.log(count)//失去响应

#解决
import {
    
     storeToRefs } from 'pinia'
const {
    
     count }  = storeToRefs(useStore())
console.log(count.value)

state

In Pinia, states are defined as functions that return an initial state.

const useStore = defineStore('main', {
    
    
    state: () => {
    
    
        return {
    
    count: 0}
})

access "state"

const storeObj = useStore()
store.count++

reset status

const storeObj = useStore()
storeObj.$reset()

change status

Can be modified by evil: store.count++

You can call the $patch method

storeObj.$patch({
    
    
    otherProp: 'main'//其他属性
    count: storeObj.count + 1
})

or

storeObj.$patch((state) => {
    
    
    state.item.push({
    
    name: 'RenNing', age: 18})
    state.count = ++state.count
})

$patchThe method also accepts a function to batch modify some objects in the collection

replacestate

store.$state = {
    
     counter: 666, name: 'Paimon' } //{ counter: 666, name: 'Paimon' }
store.$state = {
    
    }

Only for the original defined attributes, although undefined data will be added, but it will not work

subscription status

$subscribe()View the state and its changes through the store method

The advantage of watch()using over regular is that subscriptions will only be triggered once after patches$subscribe()

storeObj.$subscribe((mutation, state) => {
  // import { MutationType } from 'pinia'
  mutation.type // 'direct' | 'patch object' | 'patch function'
  // 与 cartStore.$id 相同
  mutation.storeId // 'cart'
  // 仅适用于 mutation.type === 'patch object'
  mutation.payload // 补丁对象传递给 to cartStore.$patch()

  // 每当它发生变化时,将整个状态持久化到本地存储
  localStorage.setItem('cart', JSON.stringify(state))
})

By default, state subscriptions are bound to the component that added them

They will be automatically removed when the component is unmounted

If you want to keep components after they are unmounted, pass { detached: true }as the second argument to detach the current component's state subscription

storeObj.$subscribe(callback, {
    
    detached: true})

You can piniaview the entire status on the instance:

watch(
  pinia.state,
  (state) => {
    // 每当它发生变化时,将整个状态持久化到本地存储
    localStorage.setItem('piniaState', JSON.stringify(state))
  },
  { deep: true }
)

getter

defineStore()Defined with the attribute in getters.

Accept "state" as first argument to encourage use of arrow functions

export const useStore = defineStore('count', {
    
    
    state: () =>{
    
    {
    
    count: 1}},
    getters: {
    
    
        //方法一
        doubleCount: (state) => {
    
    return state.count * 2}//方法二
        doublePlusOne(): number {
    
     return this.counter * 2 + 1 },
    }
})

Pass the parameter to the getter

# 定义
getters: {
    
    
	getUserId(state) =>{
    
    
        const arr = state.foo.filter(....)
        return (userId) => arr.find(id => userId == id)
    }
}
#使用
{
    
    {
    
    getUserId(2)}}

When you do this, the getters are no longer cached , they are just functions that you call.

However, you can cache some results inside the getter itself

Ask the getters of other Stores

import {
    
    useOtherStore} from './other-sotre'
getters: {
    
    
    otherGetter(state) {
    
    
        const otherStore = useOtherStore()
        return state.localDate + otherStore.data
    }
}

no setup()

import {
    
     mapState } from 'pinia'
computed:{
    
    
    ...mapState(useCounterStroe, ['doubleCount'])
}

Actions

Equivalent to methods in components. Good for defining business logic

export const useStore = defineStore('main', {
    
    
    actions: {
    
    
        increment() {
    
    this.count++},
        async getApi() {
    
    
            try{
    
    
                let res = await post('url',options)
            }catch{
    
    
                
            }
        }
    },
    
})

Like getters , operations can thisbe accessed via

actionscan be asynchronous

transfer

Actions are invoked like methods:

useStore.getApi()

does not apply to setup()

Action properties can mapActions()be mapped to methods in components using

import {
    
     mapActions } from 'pinia'
import {
    
     getApi } from '../stores/useStore.js'
methods:{
    
    
    ...mapActions(getApi)
}

Subscribe to Actions

store.$onAction()Subscribe to an action and its result using

const unsubscribe = someStore.$onAction(
  ({
    
    
    name, // action 的名字
    store, // store 实例
    args, // 调用这个 action 的参数
    after, // 在这个 action 执行完毕之后,执行这个函数
    onError, // 在这个 action 抛出异常的时候,执行这个函数
  }) => {
    
    
    // 记录开始的时间变量
    const startTime = Date.now()
    // 这将在 `store` 上的操作执行之前触发
    console.log(`Start "${
      
      name}" with params [${
      
      args.join(', ')}].`)

    // 如果 action 成功并且完全运行后,after 将触发。
    // 它将等待任何返回的 promise
    after((result) => {
    
    
      console.log(
        `Finished "${
      
      name}" after ${
      
      
          Date.now() - startTime
        }ms.\nResult: ${
      
      result}.`
      )
    })

    // 如果 action 抛出或返回 Promise.reject ,onError 将触发
    onError((error) => {
    
    
      console.warn(
        `Failed "${
      
      name}" after ${
      
      Date.now() - startTime}ms.\nError: ${
      
      error}.`
      )
    })
  }
)

// 手动移除订阅
unsubscribe()

Triggered when/after the method is called

By default, action subscriptions are bound to the component that added them, and by default, action subscriptions are bound to the component that added them.

If you want to keep components after they are detached, pass trueas the second argument to the current component's detach action subscription

// 此订阅将在组件卸载后保留
someStore.$onAction(callback, true)

Guess you like

Origin blog.csdn.net/weixin_46211267/article/details/132148509