Vue.jsによるバリデーションのサンプルを作ってみた

##Vue.jsを使うメリット

###導入のしやすさ
Vue.jsが流行っているのは段階的に導入を進めていきやすいからというのが挙げられると思います。また実装の規模によってCDNで導入したりnpmコマンドでVue CLIを入れてがっつりVueを使用して構築することも可能です。

###大量のイベントの記述を一掃できる
Vue.jsで実装を行うとjQueryで大量に記述するonclickなどのイベントの記述を一掃することができます。
HTMLに**$(.js-selector)**のようにクラスの先頭にjs-って付けてJSだけで使用されるクラスををたくさん記述する必要がなくなるのでHTMLの見通しも良くなります。またDOMの構造が変化してもプログラムが動かなくなることが基本的にありません。

##バリデーションのサンプルを実装した

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="result" data-user="YusukeIkeda" data-slug-hash="wRmvOO" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="wRmvOO">
  <span>See the Pen <a href="https://codepen.io/YusukeIkeda/pen/wRmvOO">
  wRmvOO</a> by YusukeIkeda (<a href="https://codepen.io/YusukeIkeda">@YusukeIkeda</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

Vue.jsでバリデーションを実装する場合、プラグインを導入する方法もありますが、まずはプラグインを使わず実装を出来た方が理解度が変わると思うので、今回はプラグインを使わないで実装をしてみました。

※この記事に載せているソースを改良したものを[こちら](https://qiita.com/ikdysk/items/87abcad80e701a6ed0d8)に掲載しなおしています。万一参考にされる場合はそちらをご覧ください。

###HTML・CSSについて
CSSに```[v-cloak] {display: none;}```という記述がありますが、これはチラツキ防止です。
Vue.jsが完全に読み込まれる前に、一瞬だけマスタッシュ構文 **{{ checkName }}** が見えてしまうのを防ぐ為、Vue.jsが完全に読み込むまで```display:none;```で見えなくしてくれます。


```html:HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Vue.jsによるサンプルバリデーション</title>
<style>
[v-cloak] {
  display: none;
}
table td{
  width: 200px;
}
table input[type="text"]{
  width: 100%;
}
</style>
</head>
<body>

<div id="app">
  <div v-cloak>
    <!--エラーメッセージ-->
    <p v-show="!this.name.flag">{{checkName}}</p>
    <p v-show="!this.tel.flag">{{checkTel}}</p>
    <p v-show="!this.email.flag">{{checkEmail}}</p>
  </div>

  <!--入力項目-->
  <form method="post" action="">
    <table>
      <tr>
        <th>名前：</th><td><input type="text" v-model="name.text"></td>
      </tr>
      <tr>
        <th>電話番号：</th><td><input type="text" v-model="tel.text"></td>
      </tr>
      <tr>
        <th>メール：</th><td><input type="text" v-model="email.text"></td>
      </tr>
    </table>
  </form>
</div>
<script src="https://unpkg.com/vue"></script>
<script src="script.js"></script>
</body>
</html>
```

###JavaScriptについて
####【実装における課題】
```if(checkval == 0) ```というif文で文字列の長さをチェックして、未入力かどうかの判定をしているけど、このif文が初回アクセス時も動いてしまう。その為画面にアクセスしたらいきなりエラーメッセージが表示される状態。対処療法として初期化の文字列に半角スペースを入れて、エラーメッセージを表示させないようにしたけど、これは根本的な解決策じゃない…。

良い解決策をご存じの方、コメントで教えていただけたら幸いです…！

```javascript:script.js
var app = new Vue({
  el: '#app',
  data: {
    name:{
      text: ' ',
      max:'名前は10文字以内で入力してください',
      require:'名前は必須です',
      flag : true,
    },
    tel:{
      text: ' ',
      max:'電話番号は10文字以内で入力してください',
      require:'電話番号は必須です',
      flag : true,
    },
    email:{
      text: ' ',
      max:'メールアドレスは100文字以内で入力してください',
      require:'メールアドレスは必須です',
      flag : true,
    },
  },
  computed: {
    checkName: function() {
      let checkval = this.name.text.length;
      if(checkval == 0) { //未入力チェック
        this.name.flag = false;
        return this.name.require;
      } else if(checkval > 10) { //文字の制限チェック
        this.name.flag = false;
        return this.name.max;
      }
      this.name.flag = true;
    },
    checkTel: function() {
      let checkval = this.tel.text.length;
      if(checkval == 0) { //未入力チェック
        this.tel.flag = false;
        return this.name.require;
      } else if(checkval > 10) { //文字の制限チェック
        this.tel.flag = false;
        return this.tel.max;
      }
      this.tel.flag = true;
    },
    checkEmail: function() {
      let checkval = this.email.text.length;
      if(checkval == 0) { //未入力チェック
        this.tel.flag = false;
        return this.name.require;
      } else if(checkval > 100) { //文字の制限チェック
        this.email.flag = false;
        return this.email.max;
      }
      this.email.flag = true;
    }
  }
});
```

#まとめ
今回のサンプルはとりあえず動くけど、実装方法は絶対に良くないのでもっと理解を深める必要があるなぁと思います。

Vue.jsは今後フロントエンドでスタンダードなフレームワークになるのかなぁと思っているのだけど、特にこだわりが無いのであれば、導入を検討しても良いんじゃないかなぁと思う。(むやみに新しい技術に飛びつくのは節操ないけど)。ある程度モダンな技術を採用しておくと採用の面でもプラスに働く可能性は高いですし、在籍しているエンジニアのスキルの向上にもなりそうです。