Skip to content
目录导航

Actions

Actions 相当于组件中的 methods。 它们可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑

js
export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
  }),
  actions: {
    // 因为我们依赖 `this`,所以我们不能使用箭头函数
    increment() {
      this.count++
    },
    randomizeCounter() {
      this.count = Math.round(100 * Math.random())
    },
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

getters 一样,操作可以通过 this 访问 whole store instance 并提供完整类型(和自动完成✨)支持与 getter 不同,actions 可以是异步的,您可以在任何 API 调用甚至其他操作的操作中await! 这是使用 Mande 的示例。 请注意,只要您获得“Promise”,您使用的库并不重要,您甚至可以使用本机的“fetch”函数(仅限浏览器):

js
import { mande } from 'mande'

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

export const useUsers = defineStore('users', {
  state: () => ({
    userData: null,
    // ...
  }),

  actions: {
    async registerUser(login, password) {
      try {
        this.userData = await api.post({ login, password })
        showTooltip(`Welcome back ${this.userData.name}!`)
      } catch (error) {
        showTooltip(error)
        // 让表单组件显示错误
        return error
      }
    },
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

你也可以完全自由地设置你想要的任何参数并返回任何东西。 调用动作时,一切都会自动推断!

Actions 像方法一样被调用:

js
export default defineComponent({
  setup() {
    const store = useCounterStore()
    // 将操作作为商店的方法调用
    store.randomizeCounter()

    return {}
  },
})
1
2
3
4
5
6
7
8
9

访问其他商店的 Actions

要使用另一个商店,您可以直接在 Action 内部使用它:

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

export const useSettingsStore = 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')
      }
    },
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Usage with setup()

您可以直接调用任何操作作为 store 的方法:

js
export default {
  setup() {
    const store = useCounterStore()

    store.randomizeCounter()
  },
}
1
2
3
4
5
6
7

使用选项式 API

对于以下示例,您可以假设已创建以下商店:

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

import { defineStore } from 'pinia',

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

With setup()

虽然 Composition API 并不适合所有人,但 setup() 钩子可以使在 Options API 中使用 Pinia 更容易。 不需要额外的地图辅助功能!

js
import { useCounterStore } from '../stores/counter'

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

    return { counterStore }
  },
  methods: {
    incrementAndPrint() {
      this.counterStore.increment()
      console.log('New Count:', this.counterStore.count)
    },
  },
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Without setup()

如果您根本不想使用 Composition API,可以使用 mapActions() 帮助器将操作属性映射为组件中的方法:

js
import { mapActions } from 'pinia'
import { useCounterStore } from '../stores/counter'

export default {
  methods: {
    // 允许访问组件内部的 this.increment()
    // 与从 store.increment() 调用相同
    ...mapActions(useCounterStore, ['increment'])
    // 与上面相同,但将其注册为 this.myOwnName()
    ...mapActions(useCounterStore, { myOwnName: 'increment' }),
  },
}
1
2
3
4
5
6
7
8
9
10
11
12

订阅action

可以使用 store.$onAction() 观察动作及其结果。 传递给它的回调在操作本身之前执行。 after 处理承诺并允许您在操作解决后执行函数。 以类似的方式,onError 允许您在操作抛出或拒绝时执行函数。 这些对于在运行时跟踪错误很有用,类似于 Vue 文档中的这个提示

这是一个在运行操作之前和它们解决/拒绝之后记录的示例。

js
const unsubscribe = someStore.$onAction(
  ({
    name, // 动作名称
    store, // 存储实例,与 `someStore` 相同
    args, // 传递给动作的参数数组
    after, // 动作返回或解决后的钩子
    onError, // 如果动作抛出或拒绝,则挂钩
  }) => {
    // 此特定操作调用的共享变量
    const startTime = Date.now()
    // 这将在 `store` 上的操作执行之前触发
    console.log(`Start "${name}" with params [${args.join(', ')}].`)

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

    // 如果动作抛出或返回拒绝的承诺,这将触发
    onError((error) => {
      console.warn(
        `Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
      )
    })
  }
)

// 手动移除监听器
unsubscribe()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

默认情况下,action subscriptions 绑定到添加它们的组件(如果商店位于组件的 setup() 内)。 意思是,当组件被卸载时,它们将被自动删除。 如果您还想在组件卸载后保留它们,请将 true 作为第二个参数传递给当前组件的 detach action subscription

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

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

    // ...
  },
}
1
2
3
4
5
6
7
8
9
10