kindle本「Vue.jsでTodoアプリを作ってみよう」のまとめ。
点数
78点
感想
内容が簡単なので、よく理解することができた。
Vuetifyが便利なので、もっと情報収集していきたい。
Vue.jsの基本
手順
npm init -y
npm install @vue/cli
vue create myapp1
cd myapp1
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>
ルーティング
vue create history-router-app
※Manually select featuresを選択⇒Routerを選択- src/components/にPageOne.vue, PageTwo.vueを作成
- 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
})
- 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アプリ作成
vue create todoapp
※Manually select featuresを選択⇒Routerを選択- App.jsを修正
<router-view/>
とするだけ。 - router/index.jsを修正
import TodoForm from '../components/TodoForm'
import TodoList from '../components/TodoList'
および
const routes = [
{
path: '/',
component: TodoList
},
{
path: '/add',
component: TodoForm
}
]
- 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('/');
}
- 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アプリに適用する
vue add vuetify
- 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>
- TodoForm.vueを修正
<div>
<v-text-field v-model="newTodo" placeholder="Todoを入力してください"/>
<v-btn @click="addTodo" dark color="indigo">登録</v-btn>
</div>
- 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">
サーバに置きたい場合、スマホアプリとして動作させたい場合、などは以下の手順が必要。
npm install material-icons
- main.jsに
import 'material-icons/iconfont/material-icons.css'
を追加 - index.htmlの
<link>
を削除