ストアの定義
コアコンセプトに入る前に、ストアは defineStore()
で定義され、最初の引数として渡される 一意 の名称が必要であることを知る必要があります:
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 useAlertsStore = defineStore('alerts', {
// other options...
})
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 useAlertsStore = defineStore('alerts', {
// other options...
})
id とも呼ばれるこの 名前 は必要であり、ストアを devtools に接続するために Pinia によって使用されます。返された関数の名前を use... にすることは、その使用方法を慣用的にするためのコンポーザブル全体の規則です。
defineStore()
は第 2 引数に 2 つの異なる値 (Setup 関数、または Options オブジェクト) を受け入れます。
Option ストア
Vue の Options API と同様に、state
、action
そして getters
プロパティを持つ Options オブジェクトを渡すこともできます。
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0, name: 'Eduardo' }),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0, name: 'Eduardo' }),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
state
はストアの data
、getters
はストアの computed
プロパティ、actions
は methods
と考えることができます。
Option ストアは、使い始めるのが直感的でシンプルに感じられる必要があります。
Setup ストア
また、ストアを定義するための別の構文もあります。Vue Composition API の setup 関数 と同様に、リアクティブなプロパティとメソッドを定義し、公開したいプロパティとメソッドを含むオブジェクトを返す関数を渡すことができます。
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 }
})
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 }
})
Setup ストア では:
ref()
がstate
のプロパティとなりますcomputed()
がgetters
となりますfunction()
がactions
となります
Setup ストアは、ストアの中にウォッチャーを作ったり、コンポーザブル を自由に使うことができるので、Option ストア に比べて柔軟性があります。しかし、SSR を使う場合は、コンポーザブルの使い方がより複雑になることに注意してください。
どちらの構文を選択する?
Vue の Composition API と Options API と同様に、最も使いやすいと感じるものを選んでください。よくわからない場合、最初に Option ストア を試してください。
ストアの利用
ストアを 定義し ているのは、use...Store()
がコンポーネントの <script setup>
内(または すべての Composable のように setup()
内)で呼ばれるまでストアは作成されないからです。
<script setup>
import { useCounterStore } from '@/stores/counter'
// access the `store` variable anywhere in the component ✨
const store = useCounterStore()
</script>
<script setup>
import { useCounterStore } from '@/stores/counter'
// access the `store` variable anywhere in the component ✨
const store = useCounterStore()
</script>
TIP
まだ setup
コンポーネントを使用していない場合でも、 マップヘルパー を使用して Pinia を使用することができます。
必要な数のストアを定義できますが、Pinia の機能を最大限に活用するには、 それぞれのストアを別のファイルで定義する必要があります (バンドラーのコード分割を自動的に許可したり、TypeScript の推論を提供するなど)。
ストアをインスタンス化すると、state
、getters
そして actions
で定義されたあらゆるプロパティにストア上で直接アクセスできるようになります。これらについては、次のページで詳しく見ていきますが、オートコンプリートが役に立ちます。
store
は reactive
でラップされたオブジェクトであることに注意してください。つまり、getters の後に .value
を記述する必要はありませんが、 setup
の props
のように、それを分解することはできません:
<script 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 // will always be "Eduardo"
doubleCount // will always be 0
setTimeout(() => {
store.increment()
}, 1000)
// ✅ this one will be reactive
// 💡 but you could also just use `store.doubleCount` directly
const doubleValue = computed(() => store.doubleCount)
</script>
<script 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 // will always be "Eduardo"
doubleCount // will always be 0
setTimeout(() => {
store.increment()
}, 1000)
// ✅ this one will be reactive
// 💡 but you could also just use `store.doubleCount` directly
const doubleValue = computed(() => store.doubleCount)
</script>
リアクティビティ(反応性)を維持したままストアからプロパティを抽出するには、storeToRefs()
を使用する必要があります。これは、すべてのリアクティブプロパティに対して refs を作成します。これは、ストアの状態のみを使用し、アクションを呼び出さない場合に便利です。アクションはストア自体にバインドされているので、ストアから直接アクションを分解できることに注意しましょう:
<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` and `doubleCount` are reactive refs
// This will also extract 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 just be destructured
const { increment } = store
</script>
<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` and `doubleCount` are reactive refs
// This will also extract 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 just be destructured
const { increment } = store
</script>