見出し画像

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

🎈 この記事はWPへ移行しました
【Nuxt.js】ちょ〜簡単!TODOリスト

# 前置き

画像1

簡単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全てクリアですね!
おめでとうございます🎉



次回はslot番外編をやります!
slot応用編にてやる予定だったものが
字数オーバーのため番外編にします。

公開予定日は12/13(金)です!

🎈 この記事はWPへ移行しました
【Nuxt.js】ちょ〜簡単!TODOリスト

いいなと思ったら応援しよう!