Vue jsの入門書を終えて…

#初めに
Vue jsの入門書をやったが実際の例が少なくあまり手を動かすことができなかった。

僕は本を読んでもコードを書かなきゃすぐに忘れるのでとりあえず学んだことをまとめたりvue jsでバリデーションを行ったりする。

#なにをするか
リアルタイムでバリデーションを行いたい場合watchというものを使う
これでデータを監視するようだ

watchで必須項目だとか有効なメールアドレスかどうかとかを監視してもしエラーがあればhtml側のv-if="error.require"みたいな感じでエラー文章を表示させる。


#デザイン側

実際作ったものはこんな感じになった。

```html
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Vue.js App</title>
    <link href="main.css" rel="stylesheet">
</head>
<body>
    <div id="app">
        <p>ユーザー名</p>
        <input type="text" v-model="name">
        <div class="nameError er" v-if="nameError.require">*必須項目です</div>
        <br>
        <p>メールアドレス</p>
        <input type="text" v-model="email">
        <div class="emailError er" v-if="emailError.require">*必須項目です</div>
        <div class="emailError er" v-if="emailError.mail">有効なメールアドレスを入力してください</div>
        <br>
        <p>パスワード</p>
        <input type="text" v-model="password">
        <div class="passwordError er" v-if="passwordError.require">*必須項目です</div>
        <div class="passwordError er" v-if="passwordError.tooShort">パスワードが短すぎます</div>
        <p>パスワード（確認）</p>
        <input type="text" v-model="passwordConfirmation">
        <div class="passwordConfirmationError er" v-if="passwordConfirmationError.require">*必須項目です</div>
        <div class="passwordConfirmationError er" v-if="passwordConfirmationError.correct">パスワードと一致しません</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.17.1/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
    <script src="main.js"></script>
</body>
</html>
```

erというクラスはエラーメッセージを赤くするために使っています。
データをnameError,emailError,passwordError,passwordConfirmationErrorと作っている
v-ifはそこに書いてある内容がtrueになれば表示しfalseであれば表示をしない。

v-modelはユーザーの入力を同期させたい場合に使う

今回の場合name,email,password,passwordConfirmationというv-modelがある

v-modelでこの値を指定していないと監視もできないので必要。


vue js側はこんな感じになっている。

```javascript

var app = new Vue({
    el: '#app',
    watch: {
        name: function(newVal,oldVal) {
            this.nameError.require = (newVal.length < 1) ? true : false;
        },
        email: function(newVal,oldVal) {
            this.emailError.require = (newVal.length < 1) ? true : false;
            this.emailError.mail = (newVal.match(/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)) ? false: true;
        },
        password: function(newVal, oldVal) {
            this.passwordError.require = (newVal.length < 1) ? true : false;
            this.passwordError.tooShort = (newVal.length < 6) ? true : false;
        },
        passwordConfirmation: function(newVal, oldVal) {
            this.passwordConfirmationError.require = (newVal.length < 1) ? true : false;
            this.passwordConfirmationError.tooShort = (newVal.length < 6) ? true : false;
        }
    },
    data: {
        name: '',
        email: '',
        password: '',
        passwordConfirmation: '',
        nameError: {
            require: true,
        },
        emailError: {
            require: true,
            mail: true 
        },
        passwordError: {
            require: true,
            tooShort: false
        },
        passwordConfirmationError: {
            require: true,
            tooShort: false,
        }
    }
})
```


watchの後に

監視するv-modelを指定してる

nameにはnameErrorというオブジェクト？を作っていて例えばnameErrorはrequire: trueというデータを持っている

このrequireがfalseになるとエラーメッセージが消える感じ。

requireをtrueやらfalseに変更しているのがwatchに書いてある

```javascript
name: function(newVal,oldVal) {
            this.nameError.require = (newVal.length < 1) ? true : false;
        },
```

v-modelのnameの新しい値が1文字以下であればnameErrorのrequireをtrueに、そうでなければfalseにしてる。


#v-on:click

とりあえずバリデーションはできたけどまだほかにもたくさん機能があるのでそれらについて書いていく。
まずv-on:click

これでクリックしたときに何かしらのイベントを行わせることができる。

例えば

```html:html
<button v-on:click="hello">hello</button>
```

```javascript:js
methods: {
  hello: function() {
    alert('hello?')
  }
}
```

と書けばボタンを押せばhello?という文字のアラートが表示される。

#v-for

配列とかの中身を一つ一つ表示したいとかの場合にv-for="user in users"みたいな感じでv-for="代入する変数名　in　繰り返しを行う配列の名前"みたいに使う。

usersにuserのデータがあるとしてすべてのuserを表示するコードをかいてみる

まずデータの設定

```javascript:js
var app = new Vue({
    el: '#app',
    data: {
        users: [
            {id:1,name:"太郎",age:20},
            {id:2,name:"次郎",age:18},
            {id:3,name:"三郎",age:16},
            {id:4,name:"四郎",age:14}
        ]
    }
})
```

表示画面

```html:html
<div id="app">
    <ul>
        <li v-for="user in users" v-bind:key="user.id">
            Name: {{ user.name }} Age: {{ user.age }}
        </li>
    </ul>
</div>
```

これでユーザ一覧を表示できる。


#computed
算出プロパティと呼ぶらしくデータに対するロジックを書いたりする

このcomputedを使ってusersの検索を実装してみる。

js側がこんなかんじになる

```javascript:js
var app = new Vue({
    el: '#app',
    data: {
        range: 20,
        limit: 2,
        users: [
            {id:1,name:"太郎",age:20},
            {id:2,name:"次郎",age:18},
            {id:3,name:"三郎",age:16},
            {id:4,name:"四郎",age:14}
        ]
    },
    computed: {
        matched: function() {
            return this.users.filter(function(el) {
                return el.age <= this.range 
            }, this)
        },
        limited: function() {
            return this.matched.slice(0, this.limit)
        }
    }
})
```

computedの中にmatchedとlimitedがある。

処理的にはmatchedはrangeを指定して

el.age <= this.range

がtrueになるものを集める。というかfilterってメソッド名なのでおそらく条件に合わないものをはじいてるかんじなのかな？

limitedでは表示する件数を指定しているがこれは返される値がusersのmatchedを満たしたものをsliceしたものであることに注意

ようは返される値にuserの情報が入っている

なのでlimitedを実装したい場合はuserを表示するところでv-for="user in limited"と書く


html側はこんな感じ

```html:html
    <div id="app">
        <input v-model.number="range">歳以下のユーザ
        <input v-model.number="limit">件を表示
        <p>{{ matched.length }}　件中 {{ limited.length }} 件を表示</p>
        <ul>
            <li v-for="user in limited" v-bind:key="user.id">
                Name: {{ user.name }} Age: {{ user.age }}
            </li>
        </ul>
    </div>
```

これで検索を実装出来た。

#methods
正直computedとmethodsの違いがいまいちわからないがcomputedはプロパティでmethodsはメソッドのよう…


#おわりに
Vue jsの力を発揮するにはVue CLIをつかえるようにならないといけないんだと思う。

個人的にはサーバーサイドで行えばよいのでは？と思うことが多かったがまだVue jsの入り口に入ったばかりなのでもっといろんなことができて便利なんだろうから勉強していきたいとおもう。

JQueryより全然たのしくて良い！:sunny: