Vueのフロントバリデーションライブラリ VeeValidate（v2系）の使い方

# 初めに
VeeValidateは最新だとv4系が出ているようですが、こちらの記事はv2系の記事です。
理由は二つあり、過去にv3系（composition-apiに対応したバージョン）を見たところかなり記法が変わっており使い勝手が変わりそうであったこと、僕が最近サーバーサイドの実装しかしておらずおらず追えていない事です（こっちは怠慢なのですみません...笑）
※ v2まではVue2（OptionsAPI）向けですがCompositionAPIでも使用できます。自分は使っています。

# 利用方法
シングルファイルコンポーネントで使用する際には下記のように普通にimportして自作のcomponentと同じ要領で使用します。

```ts
import { ValidationProvider, ValidationObserver } from 'vee-validate';
//ルールをimport 他のルールに関しては公式ドキュメント参照
import { required, email } from 'vee-validate/dist/rules'; 
```

## ValidationProvider
個々の値ごとのバリデーションを行います。inputなどのhtml要素をwrapする形で使用します。

```Vue
<ValidationProvider v-slot="{ passed, failed }" tag="div" rules="required">
    <input v-model="testValue" class="input" />
    // エラーをerrorsと言う配列で受け取れる
    <p class="error-text">{{ errors[0] }}</p>
</ValidationProvider>
```

※ 複数のルールを設定しているときは、複数のエラーが返ってくる可能性があるため、`errors`は配列になっています。
自分の場合は1つ目のエラーだけ表示すればよかったためindex番号が0番の値を出力しています。


### ValidationProviderの詳細説明
```vue
<ValidationProvider 
    v-slot="{ passed, failed }"
    tag="div" 
    rules="required"
>
```

#### v-slot:

ステータスを受け取ることが出来ます。

`passed`はバリデーションに通っている際に`true`になる

`failed`はバリデーションに引っかかっている際に`true`

他にもあるので使いたい場合は公式ドキュメントを参照してください。


#### tag:

どのタグで描画するかを指定します。


#### rules:

バリデーションルールを指定します。

複数ある場合は`|`区切りで指定できます↓

```ts
rules="required|email"
```

動的にルールを付与する（変える）事も可能（dynamic rulesと呼ぶらしいです）

```ts
:rules="`${flag ? 'required' : ''}`"
```

## ValidationObserver
formタグなど、1つの入力フォーム単位で全体を監視します。
状態を監視したい箇所全てをwrapする形で使用します。

例えば、10個ValidationProviderでラップしたinputがあったとしたらその10個全てがバリデーションに通っているか？などを取得できます。

```vue
<ValidationObserver ref="observer" v-slot="observer" tag="div">
    <form action="/hoge">
      // 1つめのinput
      <ValidationProvider>
        <input v-model="testValue" class="input" />
        <p class="error-text">{{ errors[0] }}</p>
      </ValidationProvider>
 
       // 2つめのinput
      <ValidationProvider>
        <input v-model="testValue2" class="input" />
        <p class="error-text">{{ errors[0] }}</p>
      </ValidationProvider>

      // 上記2つのinputのバリデーションの状態に応じsubmitボタンの活性/非活性を制御する
      <input :disabled="observer.invalid" type="submit" value="submitする" />
    </form>
</ValidationObserver>
```

### ValidationObserverの詳細説明

```vue
<ValidationObserver ref="observer" v-slot="observer" tag="div">
```
#### v-slot:

`ValidationProvider`と同じく、ステータスを受け取ることが出来ます。
ValidationProviderの例では展開して受け取っていましたが、名前をつけてobjectごと受け取ることも出来ます。

<br>

下記の例ではバリデーションに通っていない時にtrueが返ってきます。

（バリデーションに通っていない場合、submitボタンを非活性にしたい）

```ts
:disabled="observer.invalid"
```

<br>

#### ref:

余談ですが、scriptタグ内で取得したい時は下記のような感じで取得可能

（例）編集画面の場合は、最初から全ての入力値のバリデーションを発火させておきたいと思うがこんな感じでできます。

```vue.js
mounted() {
  // 全項目のバリデーションを発火する
  this.$refs.observer.validate();
},
```

## カスタムルール（自分でバリデーションルールを定義）
`extend`を使ってできる

```ts
import { extend } from 'vee-validate';
```

### 既存のルールのエラー文言のみを変更
既存のルールのエラー文言は英語ですが、ルールはそのままにエラー文言を変えることができます。

```ts
import { extend } from 'vee-validate';
import { required, email } from 'vee-validate/dist/rules';

extend('required', {
  ...required,
  message: 'この項目は必須やで〜',
});
```

### 完全に自分で定義
```ts
import { extend } from 'vee-validate';

// 例）半角数字のみ許容
extend('number', (value) => {
  const regex = /^[0-9]+$/;
  if (regex.test(value)) {
    return true;
  }
  return '半角数字で入力してください';
});

// 例1
extend('ルールの名前', (ユーザーの入力値) => {
  // この条件に通った際にバリデーションに通したい
  if (条件) {
    return true;
  }
  // エラーの際に返したい文言をreturn
  return '半角数字で入力してください';
});

// 例2 何パターンかエラーを返したい
extend('ルールの名前', (ユーザーの入力値) => {

  if (条件1) {
    return '条件1に見合う入力をしろ！';
  }

  if (条件2) {
    return '条件2に見合う入力をしろ！';
  }

  return true;
});
```

#### extend:

第一引数は `ValidationProvider`のrulesに指定する際の名前を命名。

第二引数は 実際の動きを定義 （`value`には入力された値が入る）

エラーの場合は文言を`return`し、バリデーションに通す場合は`true`を返す。


# 最後に
思い出しながら書いたので間違えている箇所があったらすみません！ご指摘いただけると幸いです。