LoginSignup
0
1

More than 1 year has passed since last update.

VueのCompositionAPIでPiniaを使う

Last updated at Posted at 2022-07-17

久しぶりにVueを触っていたら、最近のスタンダードがVuexからPiniaに代わったということで少し試してみました。
以下に紹介してあるコードを少し修正しています。特にgettersを追加してみました。
BUILD A TO-DO LIST APP WITH PINIA AND VUE 3

Vue公式サイト
Pinia公式サイト

コマンド

開発は以下のようなコマンドで行えます。

vue create todo
cd todo
npm install pinia
npm run serve

実行画面

image.png

ソースコード

ソースコードは以下の5ファイルになります。

  1. main.js
  2. store/useTodoListStore.js
  3. App.vue
  4. components/TodoList.vue
  5. components/TodoForm.vue

1.main.js

main.jsではuse(createPinia())でPiniaの使用を宣言します。

main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

createApp(App).use(createPinia()).mount('#app')

2.useTodoListStore.js

useTodoListStore.jsではdefineStoreによってPiniaのstoreの定義を行います。
state,getters,actionsの定義を行っていますが、Piniaではmutationsが不要であることが大きな特徴となっています。

store/useTodoListStore.js
import { defineStore } from 'pinia'

export const useTodoListStore = defineStore('todoList', {
  state: () => ({
    todoList: [],
    id: 0,
  }),
  getters: {
    doubleCount: (state) => state.todoList.length*2
  },
  actions: {
    addTodo(item) {
      this.todoList.push({ item, id: this.id++, completed: false })
    },
    deleteTodo(itemID) {
      this.todoList = this.todoList.filter((object) => {
        return object.id !== itemID
      })
    },
    toggleCompleted(idToFind) {
      const todo = this.todoList.find((obj) => obj.id === idToFind)
      if (todo) {
        todo.completed = !todo.completed
      }
    },
  },
})

3.App.vue

App.vueは2つのコンポーネントのための枠組みを与えているだけです。

App.vue
<template>
  <div>
  <TodoList />
  <TodoForm />
  </div>
</template>

<script>
import TodoList from "@/components/TodoList";
import TodoForm from "@/components/TodoForm";

export default {
  name: "TodoApp",
  components: {
    TodoList, TodoForm
  },
};
</script>

4.TodoList.vue

TodoList.vueは現在のtodoリストのリスト表示を行います。

components/TodoList.vue
<template>
<div>
  <div v-for="todo in todoList" :key="todo.id">
    <div>
      <span :class="{ completed: todo.completed }">{{ todo.item }}</span>
      <span @click.stop="toggleCompleted(todo.id)">&#10004;</span>
      <span @click="deleteTodo(todo.id)">&#10060;</span>
    </div>
  </div>
  <div>
    <span>2重カウント: {{ doubleCount }}</span>
   </div>
</div>
</template>

<script>
import { useTodoListStore } from "@/store/useTodoListStore";
import { storeToRefs } from "pinia";
export default {
  setup() {
    const store = useTodoListStore();
    const { todoList, doubleCount  } = storeToRefs(store);
    const { toggleCompleted, deleteTodo } = store;

    return { todoList, doubleCount, toggleCompleted, deleteTodo };
  },
};
</script>

<style>
.completed {
  text-decoration: line-through;
}
</style>

useTodoListStoreでstoreにアクセスします。

import { useTodoListStore } from "@/store/useTodoListStore";
---
 setup() {
---
     const store = useTodoListStore();

リアクティブな値を得るためにstoreToRefsを使うことに注意してください。ここではstateのtodoListとgettersのdoubleCountを取得しています。

    const { todoList, doubleCount  } = storeToRefs(store);

actionsの関数はリアクティブではないので、storeからそのまま取得しています。

    const { toggleCompleted, deleteTodo } = store;

5.TodoForm.vue

TodoForm.vueはtodoを追加するためのフォームです。

components/TodoForm.vue
<template>
  <form @submit.prevent="addItemAndClear(todo)">
    <input v-model="todo" type="text" /><button>Add</button>
  </form>
</template>

<script>
import { useTodoListStore } from '@/store/useTodoListStore'
import { ref } from "vue";
export default {
  setup() {
    const todo = ref('')
    const store = useTodoListStore()

    function addItemAndClear(item) {
        if (item.length === 0) {
            return
        }
        store.addTodo(item)
        todo.value = ''
    }

    return { todo, addItemAndClear }
  },
}
</script>

useTodoListStoreでstoreにアクセスします。

import { useTodoListStore } from '@/store/useTodoListStore'
---
  setup() {
---
    const store = useTodoListStore()

特にCompositionAPIの特徴ですが、setup関数内でrefを使ってリアクティブな変数todoを宣言します。todoはこのコンポーネントで使われる変数です。またsetup関数内で関数addItemAndClear()を定義して利用できるようにしています。関数addItemAndClear()内ではstore.addTodo()で直接actions関数を呼んでいます。

import { ref } from "vue";
---
  setup() {
---
    const todo = ref('')
---
    function addItemAndClear(item) {
        if (item.length === 0) {
            return
        }
        store.addTodo(item)
        todo.value = ''
    }
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1