Vee-Validate3を使ってたけど、Vue3を利用しているので、
Vue3対応版のVee-Validate4を試してみたときに備忘録。
かなり変わっているので、びっくりする(*´ω`*)
主な変更点
- ValidationProviderなどで囲わなくなり、
Form
、Field
などのコンポーネントが提供されるようになった. - validationルールは提供されなり、
Yupなどを使い自分で定義が必要に - フォームに全体のルールを設定できるようになり、
フィールドごとにルールが不要になった。
使い方
まずはインストール。
$ npm install vee-validate --save
コンポーネント版
フィールドのバリデーション
基本的には、提供されるコンポーネントを<form>
や<input>
のように使う。
必須入力であっても、validationルールは自分で作る必要がある。
・ Form-level Validation
<template> <Form> <Field name="field" :rules="isRequired" /> <ErrorMessage name="field" /> </Form> </template> <script setup> import { Field, Form, ErrorMessage } from 'vee-validate'; // validationルール: 必須 function isRequired(value) { if (value && value.trim()) { return true; } return 'This is required'; } </script>
バリデーションライブラリのYupを使うと便利らしい。
・jquense/yup: Dead simple Object schema validation
<template> <Form> <Field name="password" type="password" :rules="passwordRules" /> <ErrorMessage name="password" /> </Form> </template> <script setup> import { Field, Form, ErrorMessage } from 'vee-validate'; import * as yup from 'yup'; const passwordRules = yup.string().required().min(8); </script>
フォームレベルでのバリデーション
フィールド個別にバリデーションを書く必要がなくなったらしい。
各フィールドのルールを設定して、Form
のvalidation-schema
に設定すればよいよう。
<template> <Form @submit="submit" :validation-schema="schema"> <Field name="email" /> <ErrorMessage name="email" /> <Field name="password" type="password" /> <ErrorMessage name="password" /> <button>Submit</button> </Form> </template> <script setup> import { Form, Field, ErrorMessage } from 'vee-validate'; import * as yup from 'yup'; const schema = yup.object({ email: yup.string().required().email(), password: yup.string().required().min(8), }); </script>
Composition API版
useField
やuseForm
が用意されていて、
setup
内で完結できるよう。
フィールドのバリデーション
<template> <div> <input v-model="value" type="text" /> <span>{{ errorMessage }}</span> </div> </template> <script setup> import { defineProps, toRef } from 'vue'; import { useField } from 'vee-validate'; import * as yup from 'yup'; const props = defineProps({ name: { type: String, required: true }, }); const nameRef = toRef(props, 'name'); const { errorMessage, value } = useField(nameRef, yup.string().required().min(8)); </script>
・Field-level Validation with yup
フォームレベルでのバリデーション
<template> <div> <MyTextInput name="email" /> <MyTextInput name="password" /> </div> </template> <script setup> import { useForm, useField } from 'vee-validate'; import * as yup from 'yup'; import MyTextInput from '@/components/MyTextInput.vue'; // Define a validation schema const schema = yup.object({ email: yup.string().required().email(), password: yup.string().required().min(8), }); // Create a form context with the validation schema useForm({ validationSchema: schema, }); </script>
・Form-level Validation with yup
useFormで扱える値や関数
// in setup import { useForm } from 'vee-validate'; interface LoginForm { email: string; password: string; } const { meta, isSubmitting, errors, handleSubmit, resetForm, setErrors, setFieldValue } = useForm<LoginForm>(); // validな状態 console.log(`valid=${meta.value.valid}`); // submit中の状態 console.log(`isSubmitting=${isSubmitting.value}`); // エラーの値 errors.value; // typed as { email?: string; password?: string } // フォームの送信 const onSubmit = handleSubmit(values => { alert(JSON.stringify(values, null, 2)); }); // フォームのリセット resetForm(); // エラーメッセージの設定 setErrors({ email: 'This field is invalid', // auto-complete for `email` and `password` }); // 値の設定 setFieldValue('email', 'example@gmail.com'); // auto-complete for the field name and its value type
いずれもFormコンポーネントでも受け取れる。
<Form as="" v-slot="{ meta, isSubmitting, errors, handleSubmit, resetForm, setErrors, setFieldValue }"> <form @submit="submitForm"> <!-- ... --> </form> </Form>
・Form
Yupを使うときの注意点
1.必要なものだけインポートする
// NG: 全部をimportする import * as yup from 'yup'; // OK: 必要なものだけimportする import { object, string } from 'yup'; const schema = yup.object({ email: yup.string().email(), // ... });
2.Yup schemaのリアクティブ
スキーマが固定である場合、無駄に変更を検知しないよう、
リアクティブにしないようにする。
{ data() { // NG: リアクティブになっている const schema = yup.object({ /* ... */ }); // OK-1: markRaw()で非リアクティブ化する const schema = markRaw(yup.object({ /* ... */ })); return { schema }; }, // OK-2: setup内でref()もreactive()も使ってない setup() { const schema = yup.object({ /* ... */ }); return { schema }; }, }
以上!! 結構変わってるけど、楽になった気がする(*´ω`*)