Vue.jsでTODOリストを作りました。
完成品の確認
テキストを送信すると上のTODOリストに追加され、チェックボックスにチェックすると斜線が引かれます。
削除したい時は右のバツマークを押すと削除される仕様です。
コードの確認
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>vue.js</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="app" class="container">
<h1>TODOリスト</h1>
<div class="inner">
<ul>
<li v-for="(todo,index) in todos">
<input type="checkbox" v-model="todo.isDone">
<span :class="{done:todo.isDone}">{{todo.title}}</span>
<span @click="deliteItem(index)">✖︎</span>
</li>
</ul>
<form @submit.prevent="addItem">
<input type="text" v-model="newItem">
<button type="submit">送信</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="js/script.js"></script>
</body>
</html>
var vm = new Vue({
el:'#app',
data:{
newItem:"",
todos:[]
},
methods:{
addItem:function(){
var item = {
title: this.newItem,
isDone:false
};
this.todos.push(item);
this.newItem="";
},
deliteItem:function(index){
this.todos.splice(index,1);
}
}
})
@charset "utf-8";
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
color: #2b2b2b;
}
.container{
width: 375px;
margin:0 auto;
background-color: #eee;
height: 100vh;
}
.inner{
padding: 40px 20px;
}
h1{
background-color: darkseagreen;
color: #fff;
text-align: center;
padding: 15px 0;
}
ul li{
list-style-type: none;
line-height: 2;
font-size: 21px;
display: grid;
grid-template-columns: 1fr 8fr 1fr;
align-items: center;
}
span{
cursor: pointer;
}
input[type="checkbox"]{
width: 20px;
height: 20px;
}
form{
position: absolute;
bottom: 20px;
}
input[type="text"]{
width: 337px;
border: none;
outline: none;
padding: 10px;
}
button{
width: 50px;
height: 35px;
border: none;
background:darkseagreen;
position: absolute;
right: 0px;
cursor: pointer;
color: #fff;
}
.done{
text-decoration: line-through;
color: dimgray;
}
Vue.jsでTODOリスト作ってみた:手順
空のテンプレートの作成
まずは空のテンプレートを作り、TODOリストを作る準備をします。
<div id="app">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="js/script.js"></script>
var app = new Vue({
el:'#app',
})
リスト部分のループの作成
次にTODOリストが表示される、リスト部分の作成です。
<div id="app">
<h1>TODOリスト</h1>
<div class="inner">
<ul>
<li v-for="todo in todos">
{{todo}}
</li>
</ul>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="js/script.js"></script>
var vm = new Vue({
el:'#app',
data:{
todos:["task1","task2","task3"]
},
})
dataの中にtodosという配列を作り、データを格納します。
出力はv-forを使ってループ表示させます。書き方はこんな感じです。
v-for=”値 in 配列orオブジェクト”
リスト投稿部分の作成
<div id="app" class="container">
<h1>TODOリスト</h1>
<div class="inner">
<ul>
<li v-for="todo in todos">
{{todo}}
</li>
</ul>
<form @submit.prevent="addItem">
<input type="text" v-model="newItem">
<button type="submit">送信</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="js/script.js"></script>
var vm = new Vue({
el:'#app',
data:{
newItem:"",
todos:["task1","task2","task3"]
},
methods:{
addItem:function(){
this.todos.push(this.newItem)
this.newItem="";
},
}
})
HTMLの部分については<form>〜</form>が追加されました。
inputタグでテキスト部分を作り、buttonタグ送信ボタンを作ります。
formタグには@submit.prevent=”addItem”(v-on:submit.preven=”addItem”)を追加することで、送信ボタンを押した時にaddItemというメソッドが走ります。
@イベント名.prevent = “メソッド名”
JSの部分については、dataの中にnewItem:””を追加してあげます。
それからmethodsの中に、送信ボタンが押された時の処理(addItem)を作ります。
preventって何?
preventを付けないと送信ボタンを押したときに画面遷移してしまって、リストに追加できません。
submitイベントが元々、action属性での画面遷移を想定しているため、意図しない画面遷移を避けるためにはpreventを指定してあげる必要があります。(下記動画参照)
submitイベントが<button>ではなく、<form>についているのはなんで?
「送信ボタンが押された時」だからbuttonタグにsubmitイベントが付くんじゃないのー??って思いますよね。
私は思いました。
調べるとそもそもsubmitイベントが<form>で発生するものだとわかりました。
submit
イベントは<form>
要素自身で発生するものであり、その中の<button>
や <input type=”submit”> で発生するものではないことに注意してください。しかし、フォームの送信が起動されたことを示すために送信されるSubmitEvent
(en-US) には、送信リクエストがどのボタンで起動されたかをsubmitter
(en-US) プロパティが含まれています。
https://developer.mozilla.org/ja/docs/Web/API/HTMLFormElement/submit_event
チェックボックスの作成
チェックボックスにチェックを入れると、斜線が引かれるようにします。
<div id="app" class="container">
<h1>TODOリスト</h1>
<div class="inner">
<ul>
<li v-for="(todo,index) in todos">
<input type="checkbox" v-model="todo.isDone">
<span :class="{done:todo.isDone}">{{todo.title}}</span>
</li>
</ul>
<form @submit.prevent="addItem">
<input type="text" v-model="newItem">
<button type="submit">送信</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="js/script.js"></script>
var vm = new Vue({
el:'#app',
data:{
newItem:"",
todos:[
{
title:"task1",
isDone:false
},
{
title:"task2",
isDone:false
},
{
title:"task3",
isDone:false
}
]
},
methods:{
addItem:function(){
var item = {
title: this.newItem,
isDone:false
};
this.todos.push(item);
this.newItem="";
}
}
})
タスク1つ1つの完了状態を判定のためのisDoneプロパティをつけてあげます。
todosの配列をtitle:タスク名、isDone:true / falseという形に書き換えます。
//
<input type="checkbox" v-model="todo.isDone">
TODOリストのチェックボックス部分になります。
v-modelはvue.jsの機能で、data変数とフォームの値を連動させることが出来るため、dataの中のisDoneプロパティと連携させてあげます。(true / false で返されます)
//
<span :class="{done:todo.isDone}">{{todo.title}}</span>
リストを吐き出す部分も{{todo}}から{{todo.title}}へ変更します。
:class=”{done:todo.isDone}”(v-bind:class=”{done:todo.isDone}”)は、isDoneがtrueのときdoneというクラスが付与されるという意味です。
:class=”{style名 : 値}”
//
<li v-for="(todo,index) in todos">
todoに引数をつけて何番目のtodoかを指定しています。
削除ボタンの追加
<div id="app" class="container">
<h1>TODOリスト</h1>
<div class="inner">
<ul>
<li v-for="(todo,index) in todos">
<input type="checkbox" v-model="todo.isDone">
<span :class="{done:todo.isDone}">{{todo.title}}</span>
<span @click="deliteItem(index)">✖︎</span>
</li>
</ul>
<form @submit.prevent="addItem">
<input type="text" v-model="newItem">
<button type="submit">送信</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="js/script.js"></script>
var vm = new Vue({
el:'#app',
data:{
newItem:"",
todos:[]
},
methods:{
addItem:function(){
var item = {
title: this.newItem,
isDone:false
};
this.todos.push(item);
this.newItem="";
},
deliteItem:function(index){
this.todos.splice(index,1);
}
}
})
バツボタンを押すと項目が削除されるようにしていきます。
<span @click="deliteItem(index)">✖︎</span>
バツボタンを押すとmethodsの中のdeliteItemメソッドが動きます。
indexを持たせて何番目の項目が削除されるのか判別しています。