翻译进度
3
分块数量
0
参与人数

2.1. 定义一个 Store

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。

翻译时请参照官方英文原版文档


Defining a Store

Before diving into core concepts, we need to know that a store is defined using defineStore() and that it requires a unique name, passed as the first argument:

import { defineStore } from 'pinia'

// You can name the return value of `defineStore()` anything you want, 
// but it's best to use the name of the store and surround it with `use` 
// and `Store` (e.g. `useUserStore`, `useCartStore`, `useProductStore`)
// the first argument is a unique id of the store across your application
export const useStore = defineStore('main', {
  // other options...
})

This name, also referred as id, is necessary and is used by Pinia to connect the store to the devtools. Naming the returned function use... is a convention across composables to make its usage idiomatic.

defineStore() accepts two distinct values for its second argument: a Setup function or an Options object.

Option Stores

Similar to Vue's Options API, we can also pass an Options Object with state, actions, and getters properties.

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0, name: 'Eduardo' }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

You can think of state as the data of the store, and getters as the computed properties of the store, and actions as the methods.

Options stores should feel intuitive and simple to get started with.

Setup Stores

There is also another possible syntax to define stores. Similar to the Vue Composition API's setup function, we can pass in a function that defines reactive properties and methods and returns an object with the properties and methods we want to expose.

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const name = ref('Eduardo')
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, name, doubleCount, increment }
})

In Setup Stores:

  • ref()s become state properties
  • computed()s become getters
  • function()s become actions

Setup stores bring a lot more flexibility than Options Stores as you can create watchers within a store and freely use any composable. However, keep in mind that using composables will get more complex SSR.

What syntax should I pick?

As with Vue's Composition API and Option API, pick the one that you feel the most comfortable with. If you're not sure, try the Option Stores first.

Using the store

We are defining a store because the store won't be created until use...Store() is called inside of setup():

import { useCounterStore } from '@/stores/counter'

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

    return {
      // you can return the whole store instance to use it in the template
      store,
    }
  },
}

:::tip If you are not using setup components yet, you can still use Pinia with map helpers. ::

You can define as many stores as you want and you should define each store in a different file to get the most out of pinia (like automatically allow your bundler to code split and TypeScript inference).

Once the store is instantiated, you can access any property defined in state, getters, and actions directly on the store. We will see these in detail in the next pages but autocompletion will help you.

Note that store is an object wrapped with reactive, meaning there is no need to write .value after getters but, like props in setup, we cannot destructure it:

export default defineComponent({
  setup() {
    const store = useCounterStore()
    // ❌ This won't work because it breaks reactivity
    // it's the same as destructuring from `props`
    const { name, doubleCount } = store

    name // "Eduardo"
    doubleCount // 0

    setTimeout(() => {
      store.increment()
    }, 1000)

    return {
      // will always be "Eduardo"
      name,
      // will always be 0
      doubleCount,
      // will also always be 0
      doubleNumber: store.doubleCount,

      // ✅ this one will be reactive
      doubleValue: computed(() => store.doubleCount),
    }
  },
})

In order to extract properties from the store while keeping its reactivity, you need to use storeToRefs(). It will create refs for every reactive property. This is useful when you are only using state from the store but not calling any action. Note you can destructure actions directly from the store as they are bound to the store itself too:

import { storeToRefs } from 'pinia'

export default defineComponent({
  setup() {
    const store = useCounterStore()
    // `name` and `doubleCount` are reactive refs
    // This will also create refs for properties added by plugins
    // but skip any action or non reactive (non ref/reactive) property
    const { name, doubleCount } = storeToRefs(store)
    // the increment action can be just extracted
    const { increment } = store

    return {
      name,
      doubleCount,
      increment,
    }
  },
})

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

thebestxt
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 0
发起讨论 只看当前版本


暂无话题~