Actions
Actions 相当于组件中的 methods。 它们可以使用 defineStore()
中的 actions
属性定义,并且它们非常适合定义业务逻辑:
export const useStore = defineStore('main', {
state: () => ({
counter: 0,
}),
actions: {
increment() {
this.counter++
},
randomizeCounter() {
this.counter = Math.round(100 * Math.random())
},
},
})
与 getters 一样,操作可以通过 this
访问 whole store instance 并提供完整类型(和自动完成✨)支持。 与它们不同,actions
可以是异步的,您可以在其中await
任何 API 调用甚至其他操作! 这是使用 Mande 的示例。 请注意,只要您获得“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)
// 让表单组件显示错误
return error
}
},
},
})
你也可以完全自由地设置你想要的任何参数并返回任何东西。 调用 Action 时,一切都会自动推断!
Actions 像 methods 一样被调用:
export default defineComponent({
setup() {
const main = useMainStore()
// Actions 像 methods 一样被调用:
main.randomizeCounter()
return {}
},
})
访问其他 store 操作
要使用另一个 store ,您可以直接在操作内部使用它:
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()
一起使用
您可以直接调用任何操作作为 store 的方法:
export default {
setup() {
const store = useStore()
store.randomizeCounter()
},
}
使用选项 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()
钩子可以使在 Options API 中使用 Pinia 更容易。 不需要额外的 map helpers 功能!
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()
将操作属性映射为组件中的方法:
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()
订阅 action 及其结果。 传递给它的回调在 action 之前执行。 after
处理 Promise 并允许您在 action 完成后执行函数。 以类似的方式,onError
允许您在处理中抛出错误。 这些对于在运行时跟踪错误很有用,类似于 Vue 文档中的这个提示。
这是一个在运行 action 之前和它们 resolve/reject 之后记录的示例。
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()
默认情况下,action subscriptions 绑定到添加它们的组件(如果 store 位于组件的 setup()
内)。 意思是,当组件被卸载时,它们将被自动删除。 如果要在卸载组件后保留它们,请将 true
作为第二个参数传递给当前组件的 detach action subscription:
export default {
setup() {
const someStore = useSomeStore()
// 此订阅将在组件卸载后保留
someStore.$onAction(callback, true)
// ...
},
}