「Vue.jsでTodoアプリを作ってみよう」の感想・備忘録

スポンサーリンク

kindle本「Vue.jsでTodoアプリを作ってみよう」のまとめ。

点数

78点

感想

内容が簡単なので、よく理解することができた。

Vuetifyが便利なので、もっと情報収集していきたい。

Vue.jsの基本

手順

  1. npm init -y
  2. npm install @vue/cli
  3. vue create myapp1
  4. cd myapp1
  5. npm run serve

v-on, v-model, v-for, v-bindを使ったコンポーネント

<template>
  <div>
    <p>@click:<a href="" @click="alertHoge" data-hoge="100">{{ title }}</a></p>
    <p>@change, @input:<input @change="handleTextChange" @input="handelTextInput"/></p>
    <p>v-model:<input v-model="title"/></p>
    v-for<p v-for="food in foods" :key="food.id">{{ food.name }}<button @click="deleteFood(food.id)">削除</button></p>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      title: 'hoge',
      foods: [
        {id: 1, name: 'apple'},
        {id: 2, name: 'lemon'},
      ]
    }
  },
  methods: {
    alertHoge(e) {
      window.alert(`hoge:${e.target.dataset.hoge}`);
    },
    handleTextChange(e) {
      console.log(`change:${e.target.value}`);
    },
    handelTextInput(e) {
      console.log(`input:${e.target.value}`);
    },
    deleteFood(id) {
      this.foods = this.foods.filter((food) => food.id !== id)
    },
  }
}
</script>

コンポーネント間のやりとり

  • 親⇒子
    propsとして渡す。
  • 子⇒親
    this.$emit()を使って親のメソッドを実行する。

親コンポーネント

<Child msg="hello" @alertHoge="alertHogeHoge"/>
および
methods: {
  alertHogeHoge() {
    alert('hogehoge');
  }
}

子コンポーネント

<template>
  <h3>{{ msg }}<button @click="alertHoge">this.$emitで親のaddHogeメソッドをコール</button></h3>
</template>

<script>
export default {
  name: 'Child',
  props: {
    msg: String
  },
  methods: {
    alertHoge(){
      this.$emit('alertHoge');
    }
  }
}
</script>

ルーティング

  1. vue create history-router-app
    ※Manually select featuresを選択⇒Routerを選択
  2. src/components/にPageOne.vue, PageTwo.vueを作成
  3. router/index.jsを修正
import PageOne from '../components/PageOne'
import PageTwo from '../components/PageTwo'
および
const routes = [
  {
    path: '/',
    component: PageOne
  },
  {
    path: '/page2',
    component: PageTwo
  }
]

※ デフォルトはHashモードなので、Hisotryモードにする場合はmodeオプションを指定する

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
  1. App.vueを修正
<router-link to="/">ページ1</router-link> |
<router-link to="/page2">ページ2</router-link>
<button @click="toPage1">ページ1</button>
<button @click="toPage2">ページ2</button>
<router-view/>
および
methods: {
  toPage1() {
    this.$router.push('/');
  },
  toPage2() {
    this.$router.push('/page2');
  },
}

Todoアプリ作成

  1. vue create todoapp
    ※Manually select featuresを選択⇒Routerを選択
  2. App.jsを修正
    <router-view/>とするだけ。
  3. router/index.jsを修正
import TodoForm from '../components/TodoForm'
import TodoList from '../components/TodoList'
および
const routes = [
  {
    path: '/',
    component: TodoList
  },
  {
    path: '/add',
    component: TodoForm
  }
]
  1. TodoForm.vueを作成
<router-link to="/">一覧へ戻る</router-link>
<input type="text" v-model="newTodo"/>
<button @click="addTodo">登録</button>
および
addTodo() {
  const todos = JSON.parse(localStorage.getItem('todos')) || [];
  todos.push(this.newTodo);
  localStorage.setItem('todos', JSON.stringify(todos));
  this.newTodo = '';
  this.$router.push('/');
}
  1. TodoList.vueを作成
<router-link to="/add">登録フォームへ</router-link>
<ul>
<li v-for="(todo, i) in todos" :key="i">{{ todo }}<button @click="deleteTodo(i)">削除</button></li>
</ul>
および
created() {
  this.todos = JSON.parse(localStorage.getItem('todos')) || [];
},
methods: {
  deleteTodo(i) {
    this.todos.splice(i, 1);
    localStorage.setItem('todos', JSON.stringify(this.todos));
  }
}

VuetifyをTodoアプリに適用する

  1. vue add vuetify
  2. TodoList.vueを修正
<v-card>
  <div>
    <v-list-item v-for="(todo, i) in todos" :key="i">
      <v-list-item-content>
        <v-list-item-title>{{ todo }}</v-list-item-title>
      </v-list-item-content>
      <v-list-item-action>
        <v-btn @click="deleteTodo(i)" color="primary">
          <v-icon>mdi-delete</v-icon>
        </v-btn>
      </v-list-item-action>
    </v-list-item>
  </div>
</v-card>
  1. TodoForm.vueを修正
<div>
  <v-text-field v-model="newTodo" placeholder="Todoを入力してください"/>
  <v-btn @click="addTodo" dark color="indigo">登録</v-btn>
</div>
  1. App.vueを修正
<v-app>
  <v-main>
    <div>
      <v-toolbar color="primary" dark>
        <v-toolbar-title>Todoアプリ</v-toolbar-title>
      </v-toolbar>
    </div>
    <div>
      <v-tabs background-color="deep-purple accent-4" center-active dark>
        <v-tabs-slider color="yellow"></v-tabs-slider>
        <v-tab to="/">Todo一覧</v-tab>
        <v-tab to="/add">登録フォーム</v-tab>
      </v-tabs>
    </div>
    <div>
      <v-container fluid>
        <v-row>
          <v-col cols="3">
            <router-view />
          </v-col>
        </v-row>
      </v-container>
    </div>
  </v-main>
</v-app>

※ <v-tab>のto属性を使えば<router-link>の記述は不要

アイコンのオフライン対応

デフォルトではindex.htmlの以下のタグでアイコンデータを外部から取得している。

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">

サーバに置きたい場合、スマホアプリとして動作させたい場合、などは以下の手順が必要。

  1. npm install material-icons
  2. main.jsにimport 'material-icons/iconfont/material-icons.css'を追加
  3. index.htmlの<link>を削除

コメント