/stores/todos.ts を以下の内容で作成します。
これは次のような機能を持ったストアになります
・変数todos にTODOリストを保存
・todoOrderedDesc() でID大きい順に並べ替えてリストを返す
・addTodo() でリストの最後にメンバーを追加する
・changeName() でidで指定したメンバの名前を変更する
記述方式はOptions APIライク(Vuexに似た昔ながらの書き方)でも、Composition APIライク(Vue3の書き方)でも
どちらでも記述することができます。
ここでは Composition API ライクで記述してみます。
stores/todos.ts
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
import _ from 'lodash'
interface Todo {
id: number
name: string
}
export const useTodoStore = defineStore('todo', () => {
const todos = ref<Todo[]>([
{
id: 1,
name: 'TODOその1'
},
{
id: 2,
name: 'TODOその2'
}
])
const todoOrderedDesc = computed(() => {
return _.sortBy(todos.value, 'id').reverse()
})
function addTodo(newTodo: Todo) {
todos.value.push(newTodo)
}
function changeName(id: number, name: string) {
todos.value = todos.value.map((v) => {
return v.id === id
? {
id: id,
name: name
}
: v
})
}
return { todos, todoOrderedDesc, addTodo, changeName }
})
import { storeToRefs } from 'pinia'
import { useTodoStore } from '../stores/todos'
const todoStore = useTodoStore()
const { todos } = storeToRefs(todoStore)
storeToRefs で todos を ref にすることでリアクティブに扱うことができます。
<template>
<ul>
<li v-for="todo in todos" :key="todo.id">
<div>{{ todo.id }} : {{ todo.name }}</div>
</li>
</ul>
</template>
/stores/todos.ts に定義した更新メソッドを呼び出して値を更新します
todoStore.changeName(1, 'TODOその1 ● 変更')
(注意)直接値を更新することもできてしまいます https://github.com/vuejs/pinia/issues/58
todos.value = []
const { todos } = storeToRefs(todoStore)
↓ 次のように修正して readonly にします
const { todos: todosMutable } = storeToRefs(todoStore)
const todos = readonly(todosMutable)
これでこのコンポーネント内では「値の変更やデータの追加、削除などができない事が担保された状態」で扱うことができます。
/stores/todos.ts で定義した更新メソッドもこのコンポーネント内では実行することができなくなります
/stores/todos.ts を以下のように修正します
return { todos, todoOrderedDesc, addTodo, changeName }
↓
return { todos: readonly(todos), todoOrderedDesc, addTodo, changeName }
これで
// これは以下のエラーによって実行できなくなります
// [Vue warn] Set operation on key "value" failed: target is readonly.
todos.value = []
この方法だと更新メソッドは問題なく使用することができます。