はじめに
少し前に、TodoistからTrelloへ乗り換えたのですが、Todoistが何となく恋しかったので、
Vue.js学習のアウトプットとしてTodoistのクローンアプリを作ろうと思いました!
作ってみると学ぶことだらけで、何かにまとめたいと思ったので記事を書くことにしました。
URL https://todoist-clone-c2bd0.web.app/
使用したツール
- VueRouter
- Vuex
- Firebase
VueRouter
routerはこのような感じです。
今回作成したページは インボックス・今日・近日中・プロジェクト です。
router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "inbox",
component: () => import("../views/Inbox.vue"),
},
{
path: "/today",
name: "today",
component: () => import("../views/Today.vue"),
},
{
path: "/fewday",
name: "fewday",
component: () => import("../views/Fewday.vue"),
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
export default router;
Vuex
firebaseに格納されているtaskのデータはこんな感じです。
titleがタスクの名前
dueDateが期日になっています。
{
id:"hogehoge",
data:{
title:"string",
dueDate:{
seconds:101010101 //(timestamp)
}
}
}
storeはこんな感じです。 tasksしかないのですが学習のためと思ってモジュール化しました
store/index.js
import Vue from "vue";
import Vuex from "vuex";
import tasksModule from "./tasks";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
tasksModule,
},
});
tasks.js
import firebase from "firebase";
const state = {
tasks: [],
};
const getters = {
// Viewで使うときには並び順は期日順にしたいので、ここで並び替えの処理を書きます
tasks(state) {
let tasks = state.tasks;
tasks.sort((a, b) => {
if (a.data.dueDate.seconds < b.data.dueDate.seconds) return -1;
if (a.data.dueDate.seconds > b.data.dueDate.seconds) return 1;
});
return tasks;
},
};
const mutations = {
fetchTasks(state, data) {
state.tasks.push(data);
},
doneTask(state, id) {
state.tasks = state.tasks.filter((el) => {
return el.id != id;
});
},
addTask(state, newTask) {
state.tasks.push(newTask);
},
};
const actions = {
// firebaseから全てのタスクを取得する処理
fetchTasks({ commit }) {
firebase
.firestore()
.collection("tasks")
.get()
.then((response) => {
response.forEach((doc) =>
commit("fetchTasks", { id: doc.id, data: doc.data() })
);
});
},
// タスクを完了とする処理です。 データから削除しています。 フラグなんかをもたせる方いいかもです。
doneTask({ commit }, { id }) {
firebase
.firestore()
.collection("tasks")
.doc(id)
.delete()
.then(() => {
commit("doneTask", id);
});
},
// タスクを追加する処理です。 firebaseにpostします
addTask({ commit }, newTask) {
firebase
.firestore()
.collection("tasks")
.add(newTask)
.then((doc) => {
commit("addTask", { id: doc.id, data: newTask });
});
},
};
const tasksModule = {
namespaced: true,
state,
getters,
mutations,
actions,
};
export default tasksModule;
View
雛形となるApp.vueはこんな感じです。
App.vue
サイドバーのナビで 表示するViewを制御しています。
一番初めにタスクを取得したいのでcreatedでfetchTasksを実行します。
<template>
<div>
<nav class="uk-navbar-container uk-margin" uk-navbar id="nav">
<div class="uk-navbar-left">
<div>
<a
class="uk-navbar-toggle"
uk-navbar-toggle-icon
href=""
@click.prevent="toggleNav"
></a>
</div>
<ul class="uk-navbar-nav">
<li>
<a href="/">
<span
class="uk-icon uk-margin-small-right"
uk-icon="icon: home"
></span>
</a>
</li>
</ul>
<div class="uk-navbar-item">
<input
class="uk-input uk-form-width-medium"
type="text"
placeholder="Search"
/>
</div>
</div>
</nav>
<div>
<transition tag="div" name="slideX">
<div class="uk-width-1-4@s side-nav" v-show="isNavShow">
<ul class="uk-nav-default uk-nav-parent-icon" uk-nav>
<li class="uk-active">
<router-link to="/">インボックス</router-link>
</li>
<li class="uk-active">
<router-link to="/today">今日</router-link>
</li>
<li class="uk-active">
<router-link to="/fewday">近日中</router-link>
</li>
<li class="uk-nav-divider"></li>
</ul>
</div>
</transition>
<router-view id="container" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
isNavShow: true,
};
},
methods: {
toggleNav() {
this.isNavShow = !this.isNavShow;
},
},
created() {
this.$store.dispatch("tasksModule/fetchTasks");
},
};
</script>