Vue.jsでTODOリスト作ってみた

vue.js

<script>” title=”<script>

<script>

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を持たせて何番目の項目が削除されるのか判別しています。