簡易アプリを作ってVue.jsの基本のキを理解する


会社でこれからフロントエンド開発に取り組みそうな感じなのでその辺りの技術にこれから触れてみたいと思います。
フレームワークの選定に関しては様々な記事を拝見して、スモールスタートから始めたい、いずれ拡張ライブラリを利用したい、UI部品をコンポーネント化してごにょごにょ・・・みたいな会社の状況にも一致しそうなVue.jsを選択してみました。

【JavaScript】3大フレームワーク Angular, React, Vue.jsを比べてみよう (2018年4月)
↑フレームワーク選定でお世話になった記事ですう。それぞれの特徴はもちろん、OSSのランキングとか客観的な視点も盛り込まれていて非常に参考になりました。

本題

新しいことを始める時はなるべく公式が提供しているチュートリアルとかでやっていきたいタイプなので例に漏れずVue.jsの公式ガイドに沿ってやっていきます。
ただ、チュートリアルの項目単品だけだと実用性がピンとこないため、簡易なタスクアプリを作りながら多少は実用性を意識してやっていきます。

作ったもの

もはやありふれているタスクアプリです。

index.html
<!DOCTYPE html>
<html>
    <head>
        <!-- 開発バージョン、便利なコンソールの警告が含まれています -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <div>
                <!-- フォーム入力バインディング -->
                <input type="text" v-model="newtask" placeholder="input task">
                <!-- ユーザー入力の制御 -->
                <button v-on:click="add_task(newtask)">add</button>
                <ol>
                    <!-- ループ -->
                    <li v-for="task in tasks">
                        <input type="checkbox" v-model="task.completed">
                        <!-- 条件分岐-->
                        <span v-if="task.completed">-- Completed -></span> {{ task.name }}
                    </li>
                </ol>
            </div>
        </div>

        <script src="main.js"></script>
    </body>
</html>
main.js
var app = new Vue({
   // vueのmodelの基底となる要素を指定
  el: '#app',
  // データの初期値を指定
  data: {
    newtask: '',
    tasks: [
      { name: 'Learn JavaScript', completed: false }, 
      { name: 'Learn Vue', completed: false}, 
      { name: 'Build something awesome', completed: false}, 
    ]
  },
  // ユーザーの入力イベントにバインドする関数を定義
  methods: {
    add_task: function(newtask){
      this.tasks.push({
        name: newtask, completed: false
      })
      this.newtask = '';
    },
  },
})

Vue.jsの基本のキ

  • はじめに
  • 宣言的レンダリング
  • 条件分岐とループ
  • ユーザー入力の制御
  • フォーム入力バインディング

はじめに

vue.jsの使い方ですね。最初に読み込まれなければいけないのでheadタグ内に記述します。

index.html
<!-- 開発バージョン、便利なコンソールの警告が含まれています -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

宣言的レンダリング

vueを使うときの定型句みたいなものですね。vueインスタンスとその基底となる要素を紐つけます。

index.html
<div id="app">
    <div>
        <!-- フォーム入力バインディング -->
        <input type="text" v-model="newtask" placeholder="input task">
・
・
・
</div>
main.js
var app = new Vue({
   // vueのmodelの基底となる要素を指定
  el: '#app',
  // データの初期値を指定
  data: {
    newtask: '',
    tasks: [
      { name: 'Learn JavaScript', completed: false }, 
      { name: 'Learn Vue', completed: false}, 
      { name: 'Build something awesome', completed: false}, 
    ]
  },



})

条件分岐とループ

条件分岐やループもv-forv-ifなどのディレクティブという属性を利用してシンプルなコードで実装できました。
下記の例ではtasksという配列をfor in文で繰り返しタスクの一覧を表示します。またタスクのcompletedがtrueなら-- Completed ->という文字をタスク名の頭に入れて完了したタスクであることを簡易的に示しています。

index.html
<!-- ループ -->
<li v-for="task in tasks">
    <input type="checkbox" v-model="task.completed">
    <!-- 条件分岐-->
    <span v-if="task.completed">-- Completed -></span> {{ task.name }}
</li>

ユーザー入力の制御

要素にイベントリスナーをバインドできます。例えば、クリックしたときの挙動などです。例ではaddボタンを押下したときの挙動をjs側でadd_task()という関数で定義しています。関数の内容はtasksに追加し、テキストボックスの値をクリアするためにnewtaskを初期化しています。

index.html

<!-- ユーザー入力の制御 -->
<button v-on:click="add_task(newtask)">add</button>
main.js
methods: {
    add_task: function(newtask){
      this.tasks.push({
        name: newtask, completed: false
      })
      this.newtask = '';
    },
  },

フォーム入力バインディング

フォーム入力バインディングはガイドの別セクションでしたが、必要な機能でしたので利用しました。v-modelディレクティブを利用しVueインスタスのモデルと要素を紐つけることができます。
(ちなみにチェックボックスにv-model="task.completed"を持たせることでtasksのComletedを表現できましたが、これでうまく動いてることを正確に説明できません。。。)

index.html
<!-- フォーム入力バインディング -->
<input type="text" v-model="newtask" placeholder="input task">
・
・
・
<input type="checkbox" v-model="task.completed">

以上

まとめ

  • Vue.jsの公式ガイド のはじめにの章で紹介されている初歩的な使い方とフォーム入力バインディングのみでできました。
  • Vueインスタンスの宣言などjavascriptソースコード(今回でいうとmain.js)はHTMLがレンダリングされた後じゃないと各要素を認識できないのでHTMLの最後の方に記述しないといけません。
  • ディレクティブでソースコードをシンプルに書ける。
  • なによりjs側でDOMを全く触りませんでした。データだけに注目できることで、Viewとモデルを切り離し、ソースコードの保守性も高くなるような気がしますね。
  • これに加え、より高度な機能やコンポーネント化、エコシステムで機能拡張していけるということなので、もっと触ってみたいですね。 {^-^}