# Actions
Actions
相当于组件中的 methods
(opens new window) 。可以使用defineStore()
中的actions
属性来定义它们,并且它们非常适合定义业务逻辑:
export const useStore = defineStore('main', {
state: () => ({
counter: 0,
}),
actions: {
increment() {
this.counter++
},
randomizeCounter() {
this.counter = Math.round(100 * Math.random())
},
},
})
和getters (opens new window)一样,actions
通过this
来访问整个store
实例,还有完整的类型支持(和自动补全功能)。与它们不同的是,**actions
**可以是异步的,您可以在它们内部进行任何API
的调用,甚至其他操作!下面是一个使用Mande (opens new window)的示例。请注意,只要你得到了一个Promise
,你使用什么样的库并不重要,您甚至可以使用原生的fetch
函数(仅适用于浏览器端):
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)
// let the form component display the error
return error
}
},
},
})
您也可以完全自由地设置任何您想要的参数并返回任何东西。当调用actions
时,一切都会被自动推断出来!
actions
与methods
调用类似:
export default defineComponent({
setup() {
const main = useMainStore()
// call the action as a method of the store
main.randomizeCounter()
return {}
},
})
# 访问其他 stores 的 actions
要使用另一个store
,您可以直接在action
内部使用它:
import { useAuthStore } from './auth-store'
export const useSettingsStore = defineStore('settings', {
state: () => ({
// ...
}),
actions: {
async fetchUserPreferences(preferences) {
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.randomizeCounter()
},
}
# Options API 中的用法
对于以下示例,您可以假设创建了以下store
:
// 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() {
counterStore.increment()
console.log('New Count:', counterStore.count)
},
},
}
# 不使用 setup()
如果您根本不想使用Composition API
,您可以使用mapActions()
辅助函数将actions
属性映射为组件中的methods
:
import { mapActions } from 'pinia'
import { useCounterStore } from '../stores/counterStore'
export default {
methods: {
// gives access to this.increment() inside the component
// same as calling from store.increment()
...mapActions(useCounterStore, ['increment']),
// same as above but registers it as this.myOwnName()
...mapActions(useCounterStore, { myOwnName: 'doubleCounter' }),
},
}
# 订阅 actions
可以使用store.$onAction()
来观察actions
及其结果。传递给它的回调函数在action
本身之前执行。在处理promises
之后,允许您在action resolves
之后执行函数。类似地,onError
允许你在action
抛出或rejects
时执行函数。这些对于在运行时跟踪错误很有用,类似于Vue文档中的这个技巧。 (opens new window)
下面是一个在运行actions
之前和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()
默认情况下,action
订阅被绑定到添加它们的组件(如果store
在组件的setup()
中)。这就意味着,当组件被卸载时,它们将被自动删除。如果你想在组件卸载后保留它们,传true
作为第二个参数,以将操作订阅与当前组件分离:
export default {
setup() {
const someStore = useSomeStore()
// this subscription will be kept after the component is unmounted
someStore.$onAction(callback, true)
// ...
},
}