前置き
簡単TODOリストを作ります!
TODO追加、終わったら削除するだけの
超絶シンプルなリストです。
そのためスタイリングはほとんどしません。
今回はTODO部分のみに焦点をおいてます。
そのためデータの保存はできません。
それは有料記事にて🌟
今まで記事にしてきた、
slot・props・$emit全てを使うので
総復習ができます✍️
早速作ってみましょう!!♪
詰まったら各要素の記事を読んで
マスターしてくださいね🌟
【コンポーネント構成】
・TODO入力する部分
・リスト表示部分
・リストの進捗率表示
【データの扱い方】
親を介して、
・入力したデータをリスト表示させる
・データの個数に合った進捗率を表示させる
directory
components/
-----| Form.vue (TODO入力)
-----| ListItem.vue (リスト)
-----| List.vue (リストの繰り返し)
-----| Progressbar.vue (進捗率)
pages/
--| index.vue
Step1: リスト表示部分の作成
【コンポーネント】
・リストの箱 (ListItem.vue)
・それを繰り返すもの (List.vue)
の2つを用意し
親からデータを渡します!
【使う物】
・slot
・props
) components
まず箱だけのListItem.vueを作成!
箱の中に表示されるTODOは
テキストのみ表示できれば良いので
propsではなくslotです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<template> <div class="list-item"> <slot /> </div> </template> <script> export default { } </script> <style lang="scss" scoped> </style> |
) pages
子に渡したpropsのtodosを
親でもtodosと命名しています。
親のdata内todos: ['TODOを作る']が
List.vueのslotで反映されます!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<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
) components
子自身でリストを追加するという
イベントがあるため$emitを使います。
v-modalで表示させたいdataごと
親に渡します。
リスト追加する際、
イベント修飾子preventを使わないと
クリックした瞬間リロードされてしまいます。
https://jp.vuejs.org/v2/guide/events.html#イベント修飾子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<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> |
) pages
子のtodoAddedが起きた時
親ではnewTodoを実行
親data内のtodosに子から受け取った
todoを追加していきます。
配列の変化は公式のこちらをご覧ください。
配列に追加したければpush、
逆に削除したければsplice、です!
https://jp.vuejs.org/v2/guide/list.html#変更メソッド
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<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)を消します!
孫 < 子 の順番で記載しています✍️
) components
1 2 3 4 5 6 7 8 9 10 11 12 |
<template> <div class="list-item" @click="$emit('deleteTodo')"> <slot /> <button >delete</button> </div> </template> <script> </script> <style lang="scss" scoped> </style> |
) components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<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
) components
数値とバーをtodosの個数によって変動させます。
max値を10として、
今10分の何個TODOがあるのか
確認できるようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<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> |
) pages
countはtodosの長さ=配列個数
max値は10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<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全てクリアですね!
おめでとうございます🎉
次回はslot番外編をやります!
slot応用編にてやる予定だったものが
字数オーバーのため番外編にします。