前置き
簡単TODOリストを作ります!
TODO追加、終わったら削除するだけの
超絶シンプルなリストです。
そのためスタイリングはほとんどしません。
今まで記事にしてきた、
slot・props・$emit全てを使うので
総復習ができます✍️
早速作ってみましょう!!♪
詰まったら各要素の記事を読んで
マスターしてくださいね🌟
【コンポーネント構成】
・TODO入力する部分
・リスト表示部分
・リストの進捗率表示
【データの扱い方】
親を介して、
・入力したデータをリスト表示させる
・データの個数に合った進捗率を表示させる
【ディレクトリ の構造、ファイル名】
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 // リストを表示する箱
<template>
<div class="list-item">
<slot />
</div>
</template>
<script>
</script>
<style lang="scss" scoped>
</style>
【List.vue】
ListItem.vueを繰り返します。
ここでtodosという配列を渡したいですね。
propsの出番です!
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 // 親ページ
<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 // 入力フォーム
<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 // 親ページ
<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 // リストを表示する箱
<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 // リストを繰り返して表示させる物
<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 // 進捗バー
<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 // 親ページ
<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