#きっかけ
これまでVueを用いてアプリを作ったりしていたのですが,Vueについての基本的なことが全然理解できていなかったことやFirebaseでサイトを公開してみたかったため学習を兼ねて作ってみました.
#完成物
ToDoアプリ
#構成
"Index.vue(src/pages/Index.vue)"という大枠のページの中に,
- Todoを書きこむ"TodoForm.vue(src/components/TodoForm.vue)"
- 書き込んだTodoを表示させる"TodoList.vue(src/components/TodoList.vue)"
の2つのコンポーネントを組み込んだ形になります.
スタイルはBootstrap-Vueを使いました.
#インポート
Bootstrapの公式サイトに従ってコマンドを打ち込みます.
npm install vue bootstrap bootstrap-vue
次にindex.js内でimport
import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/pages/Index'
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
// Import Bootstrap an BootstrapVue CSS files (order is important)
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
// Make BootstrapVue available throughout your project
Vue.use(BootstrapVue)
// Optionally install the BootstrapVue icon components plugin
Vue.use(IconsPlugin)
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Index',
component: Index
}
]
})
#Index.vue
大枠となるページのファイル
<template>
<div>
<h1>ToDoリスト</h1>
<todo-form @handleParentAddTodo="handleParentAddTodo" />
<todo-list
:todos="todos"
@handleParentDeleteTodo="handleParentDeleteTodo"
@handleParentCompleteTodo="handleParentCompleteTodo" />
</div>
</template>
<script>
// TodoForm,TodoList読み込み
import TodoForm from '@/components/TodoForm'
import TodoList from '@/components/TodoList'
export default {
name: 'Todo',
components: {
TodoForm,
TodoList
},
data () {
return {
// データバインディング
todos: []
}
},
methods: {
// v-onでメソッド呼び出し
// Todoリスト追加処理
handleParentAddTodo (value) {
if (value) {
this.todos.unshift({ text: value, complete: false })
}
},
// Todoリスト完了処理
// この処理でcompleteの真偽を逆転させる
handleParentCompleteTodo (index) {
this.todos[index].complete = !this.todos[index].complete
},
// Todoリスト削除処理
// spliceで引数の一行を消去
handleParentDeleteTodo (index) {
this.todos.splice(index, 1)
}
}
}
</script>
<style>
</style>
#TodoForm.vue
Todoリストを書き込み送信するファイル
handleAddTodo関数の$emitで子コンポーネント(TodoForm.vue)から親コンポーネント(Index.vue)へイベントを放っている
<template>
<b-container>
<b-input-group>
<!-- v-model属性で双方向ディバイディング -->
<b-form-input type="text" v-model="value"/>
<b-input-group-append>
<b-button variant="primary" @click="handleAddTodo()">送信</b-button>
</b-input-group-append>
</b-input-group>
</b-container>
</template>
<script>
export default {
name: 'TodoForm',
data () {
return {
value: ''
}
},
methods: {
// 送信ボタンクリック時に処理される関数
handleAddTodo () {
// Index.vueのhandleParentAddTodoにフォーム内の値を引数に発火
this.$emit('handleParentAddTodo', this.value)
this.value = ''
}
}
}
</script>
<style>
</style>
#TodoList.vue
フォームで送信されたTodoリストを表示したり,進捗を操作するファイル
TodoFormと同様にhandleCompleteTodo関数,handleDeleteTodo関数の$emitで子コンポーネント(TodoList.vue)から親コンポーネント(Index.vue)へイベントを放っている
<template>
<b-container>
<!-- for文でTodoリストをひとつづつ処理 -->
<b-row :key="index" v-for="(todo, index) in todos" class="mt-2">
<!-- v-bindのclass属性によりcomplete時にstyleが適用 -->
<b-col cols="8" :class="[{line: todo.complete}, 'text-left']">
<h5>{{todo.text}}</h5>
</b-col>
<b-col cols="4" class="text-right">
<b-button @click="handleCompleteTodo(index)"
:variant="todo.complete ? '' : 'success'">
{{ todo.complete ? '完了' : '未完了'}}
</b-button>
<b-button @click="handleDeleteTodo(index)" variant="danger">削除</b-button>
</b-col>
</b-row>
</b-container>
</template>
<script>
export default {
name: 'TodoList',
// 親コンポーネントからv-bindで渡された値(todos)を受け取る
props: ['todos'],
methods: {
// 完了ボタンクリック時に処理される関数
handleCompleteTodo (index) {
// Index.vueのhandleParentCompleteTodoにフォーム内の値を引数に発火
this.$emit('handleParentCompleteTodo', index)
},
// 削除ボタンクリック時に処理される関数
handleDeleteTodo (index) {
// Index.vueのhandleParentDeleteTodoにフォーム内の値を引数に発火
this.$emit('handleParentDeleteTodo', index)
}
}
}
</script>
<style scoped>
.line {
text-decoration: line-through;
}
</style>
#FirebaseでHosting
以下の記事を参考にさせていただきました
#まとめ
Todoアプリの制作を通して,v-model,v-bind,v-onについて一通りさわることができた.
propsと$emitという親コンポーネントと子コンポーネントをつなぐ概念について理解できた.
Firebaseで簡単にサイト公開をすることができた.