4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Nuxt.js】ちょ〜簡単!TODOリスト

Posted at

前置き

picture_pc_e707cf860502e0ddeeeecda8740b1f6d.gif

簡単TODOリストを作ります!
TODO追加、終わったら削除するだけの
超絶シンプルなリストです。
そのためスタイリングはほとんどしません。

今まで記事にしてきた、
slot・props・$emit全てを使うので
総復習ができます✍️
早速作ってみましょう!!♪
詰まったら各要素の記事を読んで
マスターしてくださいね🌟

【コンポーネント構成】
・TODO入力する部分
・リスト表示部分
・リストの進捗率表示

【データの扱い方】
親を介して、
・入力したデータをリスト表示させる
・データの個数に合った進捗率を表示させる

【ディレクトリ の構造、ファイル名】

file

components/
-----| Form.vue (TODO入力)
-----| ListItem.vue (リスト)
-----| List.vue (リストの繰り返し)
-----| Progressbar.vue (進捗率)

pages/
--| index.vue

Step1: リスト表示部分の作成

【コンポーネント】
・リストの箱 (ListItem.vue)
・それを繰り返すもの (List.vue)
の2つを用意し
親からデータを渡します!
【使う物】
・slot
・props
【List.vue】
まず箱だけのListItem.vueを作成!
箱の中に表示されるTODOは
テキストのみ表示できれば良いので
propsではなくslotです。

ListItem.vue
ListItem.vue // リストを表示する箱
<template>
 <div class="list-item">
   <slot />
 </div>
</template>

<script>
</script>

<style lang="scss" scoped>
</style>

【List.vue】
ListItem.vueを繰り返します。
ここでtodosという配列を渡したいですね。
propsの出番です!

List.vue
List.vue // リストを繰り返して表示させる物
<template>
 <div class="list">
   <ListItem
    v-for="todo in todos"
   >
     {{ todo }}
   </ListItem>
 </div>
</template>

<script>
import ListItem from '~/components/ListItem.vue'

export default {
 components: {
   ListItem
 },
 props: ['todos'],
}
</script>

<style lang="scss" scoped>
</style>

【index.vue】
子に渡したpropsのtodosを
親でもtodosと命名しています。
親のdata内todos: ['TODOを作る']が
List.vueのslotで反映されます!

index.vue
index.vue // 親ページ
<template>
 <div class="page">
   <List
    :todos="todos"
   />
 </div>
</template>

<script>
import List from '~/components/List.vue'

export default {
 components: {
   List
 },
 data () {
   return {
     todos: ['TODOを作る'],
   }
 },
}
</script>

<style lang="scss">
</style>

Step2:TODO入力部分の作成

【コンポーネント】
・Form.vue
【使う物】
・$emit
【Form.vue】
子自身でリストを追加するという
イベントがあるため$emitを使います。

v-modalで表示させたいdataごと
親に渡します。
リスト追加する際、
イベント修飾子preventを使わないと
クリックした瞬間リロードされてしまいます。
https://jp.vuejs.org/v2/guide/events.html#イベント修飾子

Form.vue
Form.vue // 入力フォーム
<template>
 <div class="form">
   <form @submit.prevent="todoAdd">
     <label>やること</label>
     <input v-model="todo">
     <button type="submit">Add</button>
   </form>
 </div>
</template>

<script>
export default {
 data () {
   return {
     todo: '',
   }
 },
 methods: {
   todoAdd () {
     this.$emit('todoAdded', this.todo);
     this.todo = '';
   }
 },
}
</script>

<style lang="scss" scoped>
</style>

【index.vue】
子のtodoAddedが起きた時
親ではnewTodoを実行
親data内のtodosに子から受け取った
todoを追加していきます。

配列の変化は公式のこちらをご覧ください。
配列に追加したければpush、
逆に削除したければsplice、です!
https://jp.vuejs.org/v2/guide/list.html#変更メソッド

index.vue
index.vue // 親ページ
<template>
 <div class="page">
   <Form @todoAdded="newTodo" />
   <List class="todos" :todos="todos"/>
 </div>
</template>

<script>
import List from '~/components/List.vue'
import Form from '~/components/Form.vue'

export default {
 components: {
   List,
   Form
 },
 data () {
   return {
     todo: ['TODOを作る'],
   }
 },
 methods: {
   newTodo (todo) {
     this.todos.push(todo);
   }
 },
}
</script>

<style lang="scss">
</style>

Step3:TODO完了後に削除できるようにする

【コンポーネント】
・ListItem.vue
・List.vue
【使う物】
・$emit
todoを押したら、
該当todoが消えるようにしましょう!
Listコンポーネントで
クリックすれば消えるイベントを作成し、
該当する配列番号(index)を消します!
【ListItem.vue】

ListItem.vue
ListItem.vue // リストを表示する箱
<template>
 <div class="list-item" @click="$emit('deleteTodo')">
   <slot />
   <button >delete</button>
 </div>
</template>

<script>
</script>

<style lang="scss" scoped>
</style>

【List.vue】
deleteTodoイベントを受け取り
親から渡されたpropsの
todosの配列番号のうち1つを消します。

List.vue
List.vue // リストを繰り返して表示させる物
<template>
 <div class="list">
   <ListItem
     class="list"
     v-for="(todo, index) in todos"
     @deleteTodo="todos.splice(index, 1)"
   >
     {{ todo }}
   </ListItem>
 </div>
</template>

<script>
import ListItem from '~/components/ListItem.vue'

export default {
 components: {
   ListItem
 },
 props: ['todos'],
 methods: {
   deleteTodo (index) {
     this.$emit('deleted', index)
   }
 },
}
</script>

<style lang="scss" scoped>
</style>

Step4:Progressbarの作成

【コンポーネント】
・Progressbar
【使う物】
・props
【Propgressbar.vue】
数値とバーをtodosの個数によって変動させます。
max値を10として、
今10分の何個TODOがあるのか
確認できるようにしましょう。

Progressbar.vue
Progressbar.vue // 進捗バー
<template>
 <div class="progressbar" :style="{width: (count / max ) * 100 + '%'}">
   {{ count }} / {{ max }}
 </div>
</template>

<script>
export default {
 props: ['count', 'max']
}
</script>

<style lang="scss" scoped>
</style>

【index.vue】
countはtodosの長さ=配列個数
max値は10

index.vue
index.vue // 親ページ
<template>
 <div class="page">
   <Progressbar
     :count="todos.length"
     :max="max"
   />
   <Form @listAdded="newTodo" />
   <List class="list" :todos="todos" />
 </div>
</template>

<script>
import List from '~/components/List.vue'
import Form from '~/components/Form.vue'
import Progressbar from '~/components/Progressbar.vue'

export default {
 components: {
   List,
   Form,
   Progressbar,
 },
 data () {
   return {
     todos: ['TODOを作る'],
     max: 10,
   }
 },
 methods: {
   newTodo (todo) {
     this.todos.push(todo);
   },
 },
}
</script>

<style lang="scss">
</style>

できましたか?🌟
slot, props, $emit全てクリアですね!
おめでとうございます🎉

このアカウントでは
Nuxt.js、Vue.jsを誰でも分かるよう、
超簡単に解説しています🎈😀
これからも発信していくので、
ぜひフォローしてください♪

https://twitter.com/aLizlab

4
3
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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?