跳至内容

组合 Store

组合 Store 指的是 Store 之间相互使用,Pinia 支持这种方式。需要遵循一条规则

如果 **两个或多个 Store 相互使用**,它们不能通过 GetterAction 创建无限循环。它们不能在 setup 函数中 **同时** 直接读取彼此的状态

js
const useX = defineStore('x', () => {
  const y = useY()

  // ❌ This is not possible because y also tries to read x.name
  y.name

  function doSomething() {
    // ✅ Read y properties in computed or actions
    const yName = y.name
    // ...
  }

  return {
    name: ref('I am X'),
  }
})

const useY = defineStore('y', () => {
  const x = useX()

  // ❌ This is not possible because x also tries to read y.name
  x.name

  function doSomething() {
    // ✅ Read x properties in computed or actions
    const xName = x.name
    // ...
  }

  return {
    name: ref('I am Y'),
  }
})

嵌套 Store

请注意,如果一个 Store 使用另一个 Store,你可以在 ActionGetter 中直接导入并调用 useStore() 函数。然后,你可以像在 Vue 组件中一样与 Store 进行交互。请参阅 共享 Getter共享 Action

对于 setup Store,你只需在 Store 函数的 **顶部** 使用其中一个 Store

ts
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', () => {
  const user = useUserStore()
  const list = ref([])

  const summary = computed(() => {
    return `Hi ${user.name}, you have ${list.value.length} items in your cart. It costs ${price.value}.`
  })

  function purchase() {
    return apiPurchase(user.id, this.list)
  }

  return { summary, purchase }
})

共享 Getter

你只需在 Getter 中调用 useOtherStore()

js
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  getters: {
    summary(state) {
      const user = useUserStore()

      return `Hi ${user.name}, you have ${state.list.length} items in your cart. It costs ${state.price}.`
    },
  },
})

共享 Action

Action 也是如此

js
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  actions: {
    async orderCart() {
      const user = useUserStore()

      try {
        await apiOrderCart(user.token, this.items)
        // another action
        this.emptyCart()
      } catch (err) {
        displayError(err)
      }
    },
  },
})

由于 Action 可以是异步的,请确保 **所有 useStore() 调用都出现在任何 await 之前**。否则,这可能会导致在 SSR 应用程序 中使用错误的 Pinia 实例

js
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  actions: {
    async orderCart() {
      // ✅ call at the top of the action before any `await`
      const user = useUserStore()

      try {
        await apiOrderCart(user.token, this.items)
        // ❌ called after an `await` statement
        const otherStore = useOtherStore()
        // another action
        this.emptyCart()
      } catch (err) {
        displayError(err)
      }
    },
  },
})