ローカル環境でVue.jsを使ったToDoアプリを作成する方法(初心者向け・簡単)

vue-js-prograshi(プロぐらし)-kv Vue.js
記事内に広告が含まれていることがあります。

ローカル環境で次のような機能を持ったToDoアプリをVue.jsを使って作成する手順についてまとめています。

実装する機能

  • listの追加
  • 追加したリストの個々削除
  • 空の入力値の場合追加しない
  • 完了・未完了のチェックボックス


作業手順

作成までのひとつひとつの流れは以下のようになります。

  1. Vue.jsの読み込み
  2. Vueインスタンスの作成
  3. 空のルートテンプレートの作成
  4. テンプレートのマウント
  5. 見出し設置
  6. フォーム作成
  7. 入力欄作成
  8. ボタンの作成
  9. クリックイベントの設置
  10. フォームsubmitの無効化(イベント修飾子.prevent)
  11. inputタグ内容の双方向バインディング
  12. 追加内容を格納する配列を作成
  13. 配列にタスクを追加する処理を作成
  14. タスク追加後にinputタグの表示を消去
  15. inputタグが空ならタスクを追加しない
  16. タスクを表示する
  17. チェックボックスの表示とステータス管理
  18. リストマークの非表示
  19. タスク完了時に取消線を設置
  20. タスク削除機能

Vue.jsの読み込み

<body>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


Vue.jsの読み込み

CDNで読み込みます。HTMLファイルを用意して下記のscriptのコードを記載します。

・body終端タグの上に記述。
・真下でjsファイルを読み込む。

<body>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>


Vueインスタンスの作成

.jsファイルを作成して、Vueインスタンスを作成する処理を記述します。

var app = new Vue({

})


空のルートテンプレートの作成

HTMLファイルをVue.js用の空のルートテンプレートファイルにします。

用語は難しいですが、id名がappのdivタグを用意して、上記で作成したjavascriptファイルを読み込むだけです。

<body>
    <div id="app">

    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


ルートテンプレートをマウント

上記のHTMLファイルでVue.jsが使えるように、JavaScriptファイルに el: '#app', を追記します。

var app = new Vue({
    el: '#app',
})

以上で、Vue.jsを使うための準備は完了です。

見出し設置

<body>
    <div id="app">
        <h1>To Do List</h1>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


フォーム作成

<body>
    <div id="app">
        <h1>To Do List</h1>
     <!-- ▼追加 -->
        <form action="">
        </form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


入力欄の作成

<body>
    <div id="app">
        <h1>To Do List</h1>
        <form action="">
     <!-- ▼追加 -->
        <input type="text" >
        </form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


ボタンの作成

<body>
    <div id="app">
        <h1>To Do List</h1>
        <form action="">
            <input type="text" >
     <!-- ▼追加 -->
            <button>追加</button>
        </form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


クリックイベントの設置

<body>
    <div id="app">
        <h1>To Do List</h1>
        <form action="">
            <input type="text" >
     <!-- ▼追加 -->
            <button v-on:click="addItem">追加</button>
        </form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>
var app = new Vue({
    el: "#app",
    // ▼追加
    methods:{
        addItem:function(event){
        }
    }
})


フォームのsubmitを無効化

イベント修飾子 .preventを使って、フォームで次ページのロードを無効にします。

v-on:submit.prevent

<body>
    <div id="app">
        <h1>To Do List</h1>
     <!-- ▼追加 -->
        <form v-on:submit.prevent>
            <input type="text" >
            <button v-on:click="addItem">追加</button>
        </form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


inputタグ内容の双方向バインディング

・inputタグの入力内容を保存するdataオプションを作成
・プロパティ名はnewItem
・デバッグ用にdataオプションの中身を表示

var app = new Vue({
    el: "#app",
    // ▼追加
    data:{
        newItem:''
    },
    methods:{
        addItem:function(event){
        }
    }
})


<body>
    <div id="app">
        <h1>To Do List</h1>
        <form v-on:submit.prevent>
     <!-- ▼追加 -->
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">追加</button>
        </form>
        <pre>{{$data}}</pre>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


追加内容を格納する配列を作成

・タスク追加用配列として、tasks[]を用意。

var app = new Vue({
    el: "#app",
    data:{
        newItem:'',
        // ▼追加
        tasks: []
    },
    methods:{
        addItem:function(event){
        }
    }
})


配列にタスクを追加する処理を作成

・クリックする毎に、itempプロパティを作成する。
・itemプロパティを配列に格納する。
・イベント修飾子 .push を使用。

var app = new Vue({
    el: "#app",
    data:{
        newItem:'',
        tasks: []
    },
    methods:{
        addItem:function(event){
            // ▼追加
            var task = {
                item: this.newItem
            };

            this.tasks.push(task);
        }
    }
})

ボタンクリックで {item: this.newItem} を生成。
.pushで、tasks[]の中に追加。


タスク追加後にinputタグの表示を消去

var app = new Vue({
    el: "#app",
    data:{
        newItem:'',
        tasks: []
    },
    methods:{
        addItem:function(event){
            var task = {
                item: this.newItem
            };

            this.tasks.push(task);
            // ▼追加
            this.newItem = '';
        }
    }
})


inputタグが空ならタスクを追加しない

・ifで条件分岐を設定 (※イコールは2つ)
・returnで処理を終了

var app = new Vue({
    el: "#app",
    data:{
        newItem:'',
        tasks: []
    },
    methods:{
        addItem:function(event){
            // ▼追加
            if(this.newItem =='') return;

            var task = {
                item: this.newItem
            };

            this.tasks.push(task);
            this.newItem = '';
        }
    }
})


タスクを表示する

・v-for=”変数名 in 配列”
・マスタッシュ構文 {{変数名}}
・変数のプロパティを抜き出す 変数名.プロパティ名

<body>
    <div id="app">
        <h1>To Do List</h1>
        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">追加</button>
        </form>
     <!-- ▼追加 -->
        <li v-for="task in tasks">
            <span>{{task.item}}</span>
        </li>
        <pre>{{$data}}</pre>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


チェックボックスの表示とステータス管理

・チェックボックスの初期値をfalse(チェックなし)にする
・inputタグのtype=”checkbox”にv-modelを記述すると、チェックボックスのステータスを双方向バインディングできる

var app = new Vue({
    el: "#app",
    data:{
        newItem:'',
        tasks: []
    },
    methods:{
        addItem:function(event){
            if(this.newItem =='') return;

            var task = {
                item: this.newItem,
            // ▼追加
                isActive: false
            };

            this.tasks.push(task);
            this.newItem = '';
        }
    }
})
<body>
    <div id="app">
        <h1>To Do List</h1>
        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">追加</button>
        </form>
        <li v-for="task in tasks">
     <!-- ▼追加 -->
            <input type="checkbox" v-model="task.check">
            <span>{{task.item}}</span>
        </li>
        <pre>{{$data}}</pre>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


リストマークの非表示

・cssで設定

#app li{
    list-style: none;
}

※HTMLファイルのheadタグ内でcssファイルを読み込む。
<link rel="stylesheet" href="css/main.css">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To do App</title>
    <link rel="stylesheet" href="css/main.css">
</head>


タスク完了時に取消線を設置

・cssのバインディングを使用 
v-bind:class{クラス名:真偽値}
  ┗ trueの時のみ指定したclass属性を付与

<body>
    <div id="app">
        <h1>To Do List</h1>
        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">追加</button>
        </form>
        <li v-for="task in tasks">
            <input type="checkbox" v-model="task.isActive">
     <!-- ▼追加 -->
            <span v-bind:class="{active:task.isActive}">{{task.item}}</span>
        </li>
        <pre>{{$data}}</pre>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>

<span v-bind:class="{active:task.isActive}">{{task.item}}</span>

・spanタグにclass=activeをバインド。
・isActiveの値がtrueなら属性を付与。falseなら付与しない。


CSSファイルを次のように変更します。

#app li{
    list-style: none;
}

#app li > span.active{
    text-decoration: line-through;
}


タスク削除機能

・削除ボタンの設置
・削除ボタンとインデックス番号を連動
 ┗ v-for=”(変数1, 変数2) in 配列”
  → 変数2にインデックス番号が入る
・要素の削除 .spliceを使用
.splice(開始配列番号, 削除する配列数)
 → array.splice(2,2): 3つ目の要素から2つの要素を削除

var app = new Vue({
    el: "#app",
    data:{
        newItem:'',
        tasks: []
    },
    methods:{
        addItem:function(event){
            if(this.newItem =='') return;

            var task = {
                item: this.newItem,
                isActive: false
            };

            this.tasks.push(task);
            this.newItem = '';
        },
        // ▼追加
        deleteItem:function(index){
            this.tasks.splice(index, 1)
        }
    }
})
<body>
    <div id="app">
        <h1>To Do List</h1>
        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">追加</button>
        </form>
     <!-- ▼追加 -->
        <li v-for="(task, index) in tasks">
            <input type="checkbox" v-model="task.isActive">
            <span v-bind:class="{active:task.isActive}">{{task.item}}</span>
            <button v-on:click="deleteItem">削除</button>
        </li>
        <pre>{{$data}}</pre>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>


完成版のコード

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To do App</title>
    <link rel="stylesheet" href="css/main.css">
</head>
<body>
    <div id="app">
        <h1>To Do List</h1>
        <form v-on:submit.prevent>
            <input type="text" v-model="newItem">
            <button v-on:click="addItem">追加</button>
        </form>
        <li v-for="(task, index) in tasks">
            <input type="checkbox" v-model="task.isActive">
            <span v-bind:class="{active:task.isActive}">{{task.item}}</span>
            <button v-on:click="deleteItem">削除</button>
        </li>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="js/main.js"></script>
</body>
</html>
var app = new Vue({
    el: "#app",
    data:{
        newItem:'',
        tasks: []
    },
    methods:{
        addItem:function(event){
            if(this.newItem =='') return;

            var task = {
                item: this.newItem,
                isActive: false
            };

            this.tasks.push(task);
            this.newItem = '';
        },
        deleteItem:function(index){
            this.tasks.splice(index, 1)
        }
    }
})
#app li{
    list-style: none;
}

#app li > span.active{
    text-decoration: line-through;
}
タイトルとURLをコピーしました