Pinia学习笔记之--核心概念Actions

18 篇文章 5 订阅

Actions

Actions相当于组件中的方法。他们可以被定义在defineStore()actions属性下,它们非常适合定义业务逻辑。

export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  actions: {
    increment() {
      this.counter++
    },
    randomizeCounter() {
      this.counter = Math.round(100 * Math.random())
    },
  },
})

getter一样,actions通过this(和自动完成✨)支持来访问整个store实例。与它们不同的是,actions可以是异步的,您可以在其中await任何API调用或甚至其他操作!下面是一个使用Mande的例子。注意,你只需要得到一个Promise,至于使用的库并不重要,你甚至可以使用原生的fetch函数(仅适用于浏览器):

import { mande } from 'mande'

const api = mande('/api/users')

export const useUsers = defineStore('users', {
    state: () => ({
        userDate: null
    }),
    actions: {
        async registerUser(login, password) {
            try {
                this.userDate = await api.post({ login, password})
                showTooltip(`Welcome back ${this.userData.name}!`)
            } catch (error) {
                showTooltip(error)
                // 让组件显示错误信息
                return error
            }
        }
    }
})

你可以完全自主的定义参数或返回的值。
当调用actions,一切将会被自动推断出来!
Actions像方法一样被调用:

export default defineComponent({
    setup () {
        const main = useMainStore()
        // 调用action作为store的一个方法
        main.randomizeCounter()
        return {}
    }
})

访问其它storesactions

要使用另一个store,你可以直接在action中使用它:

import { useAuthStore } from './auth-store'

export const useSettingStore = defineStore('settings', {
    state: () =>({
        preferences: null,
        //...
    }),
    actions: {
        async fetchUserPreferences() {
            const auth = useAuthStore()
            if (auth.isAuthenticated) {
                this.preferences = await fetchPreferences()
            } else {
                throw new Error('User must be authenticated')
            }
        }
    }
})

setup()中使用

你可以直接调用任何action作为store的方法:

export default {
    setup() {
        const store = useStore()
        store.fetchUserPreferences()
    }
}

使用选项API

对于以下示例,您可以假设创建了以下存储:

// Example File Path:
// ./src/stores/counterStore.js

import { defineStore } from 'pinia',

const useCounterStore = defineStore('counterStore', {
  state: () => ({
    counter: 0
  }),
  actions: {
    increment() {
      this.counter++
    }
  }
})

使用setup()

虽然Composition API并不适合所有人,但是setup()钩子可以让Pinia更容易在Options API中使用。不需要额外的帮助函数!

import { useCounterStore } from '../stores/counterStore'

export default {
  setup() {
    const counterStore = useCounterStore()

    return { counterStore }
  },
  methods: {
    incrementAndPrint() {
      this.counterStore.increment()
      console.log('New Count:', this.counterStore.count)
    },
  },
}

不使用setup()

如果你根本不想使用Composition API,你可以使用mapActions()助手来将actions属性映射为组件中的方法:

import { mapActions } from 'pinia'
import { useCounterStore } from '../stores/counterStore'

export default {
  methods: {
    // 在组件内可以通过this.increment()访问
    // 和使用 store.increment()相同
    ...mapActions(useCounterStore, ['increment'])
    // 和上面一样,但是被注册成this.myOwnName()
    ...mapActions(useCounterStore, { myOwnName: 'doubleCounter' }),
  },
}

订阅actions

可以使用store.$onAction()来观察操作及其结果。传递给它的回调函数在动作本身之前执行。after允许您在动作执行成功或resolves之后执行一个函数。类似地,onError允许你在动作抛出或拒绝时执行一个函数。这在运行时跟踪错误是非常有用的。

下面是一个在运行操作之前和resolve/reject操作之后记录日志的例子。

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()

默认情况下,操作订阅被绑定到添加它们的组件上(如果store在组件的setup()中)。这意味着,当组件被卸载后,他们将会被自动移除。如果你想在组件卸载后保持订阅,通过true作为第二个参数去把订阅从当前组件中分离出来。

export default {
  setup() {
    const someStore = useSomeStore()
    // 这个订阅将会被保留,在组件被卸载之后
    someStore.$onAction(callback, true)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绝对零度HCL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值