はじめに
Vueでフォームを作ると、v-modelでデータを繋いだあとに必須チェックやメール形式のチェックを自前で書き、エラーメッセージ用のrefを項目ごとに用意して……という作業が積み重なっていきます。項目が増えるたびにテンプレートとロジックの対応が煩雑になり、どのエラーがどの入力に紐づいているのか追いづらくなった経験がある方も多いのではないでしょうか。
Vee-Validateは、こうしたVueのフォームバリデーションをComposition APIでひとまとめに扱えるライブラリです。useFormとuseFieldという2つの関数だけで、値の保持・検証・エラーメッセージ・送信制御までをまとめて管理できます。YupやZodのようなスキーマライブラリと組み合わせることもでき、テンプレート寄りに書きたい場合はForm・Fieldコンポーネントも用意されています。
とはいえ、読むより触った方が早いと思います。ブラウザ上でVee-Validateのバリデーションがリアルタイムに反応する様子を確認できるサンプルを用意したので、先に挙動を見たい方はこちらからどうぞ。
Vee-Validateとは
Vee-Validate(GitHub: logaretm/vee-validate)は、「Painless Vue forms」を掲げるVue.js向けのフォームバリデーションライブラリです。作者のAbdelrahman Awad氏によって開発され、2026年時点でGitHubスターは11,000超え、npm最新版は4.15.1と活発にメンテナンスされています。
主な特徴
- Composition API中心の設計 -
useFormでフォーム全体を、useFieldで個々のフィールドを管理する。同じコンポーネント内で両者を呼ぶだけで、フィールドが自動的にフォームへ登録される - ヘッドレス - 独自のUIやCSSを持たず、
<input>や自作コンポーネントにそのまま値とエラーを結び付けられる。デザインシステムを問わず組み込める - スキーマライブラリを選べる -
@vee-validate/zodや@vee-validate/yupが提供するtoTypedSchemaを使うと、ZodやYupのスキーマをそのままバリデーションルールとして使え、TypeScriptの型もスキーマから導出される - 配列・ネストしたフィールドに対応 -
useFieldArrayで「メンバーを動的に追加・削除できるフォーム」のような可変長の入力を扱える - テンプレート派にも対応 - Composition APIだけでなく、
Form・Field・ErrorMessageコンポーネントを使えば、<script setup>をほとんど書かずにテンプレートだけでバリデーションを組める
インストール
npmまたはyarnでインストールします。
npm install vee-validate
yarn add vee-validate
ZodやYupのスキーマを使う場合は、対応するアダプタパッケージも合わせてインストールします。
npm install @vee-validate/zod zod
Vee-Validateのサンプルを動かす
以下は、useFormとuseFieldを使って氏名とメールアドレスを検証するサンプルです。useFieldの第2引数に渡した関数がバリデーションルールになり、入力するたびにエラーメッセージが更新されます。フォーム全体の状態はmeta.validで参照できます。
まず要点となる部分だけを抜き出すと、次のようになります。
<script setup>
import { useForm, useField } from 'vee-validate'
useForm({ initialValues: { email: '' } })
const { value: email, errorMessage } = useField('email', (value) => {
if (!value) return 'メールアドレスは必須です'
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return '形式が不正です'
return true
})
</script>
<template>
<input v-model="email" />
<span>{{ errorMessage }}</span>
</template>
実際に動かせるものが下です。氏名を空にしたり、メールアドレスから@を消したりすると、Vee-Validateが即座に反応する様子を確認できます。
useFieldは、同じコンポーネント内にuseFormがあると自動的にそのフォームへ登録されます。そのため、フィールドごとのerrorMessageだけでなく、useFormが返すmeta.validでフォーム全体の有効性もまとめて把握できます。検証ルールの関数を書き換えれば、そのまま制約を追加・変更できます。
基本的な使い方
Vee-Validateの基本形は、useFieldの第2引数にバリデーション関数(またはルール文字列)を渡すことです。関数がtrueを返せば成功、文字列を返せばその文字列がエラーメッセージになります。
import { useField } from 'vee-validate'
const { value, errorMessage, meta } = useField('username', (value) => {
if (!value) return 'ユーザー名は必須です'
if (value.length < 3) return '3文字以上で入力してください'
return true
})
console.log(meta.valid) // 初期状態はfalse(未検証)
value.value = 'ab'
console.log(errorMessage.value) // '3文字以上で入力してください'
複数のフィールドをまとめて扱う場合はuseFormを併用し、handleSubmitでバリデーション済みの値だけを送信処理に渡します。
import { useForm, useField } from 'vee-validate'
const { handleSubmit } = useForm()
const { value: username } = useField('username', (v) => (v ? true : '必須です'))
const onSubmit = handleSubmit((values) => {
// values はすべてのフィールドが検証を通過した状態で渡される
console.log(values)
})
実践的なユースケース
Zodスキーマによるバリデーション
フィールドごとにルール関数を書く代わりに、Zodなどのスキーマライブラリでオブジェクト全体のルールをまとめて定義したいケースがあります。@vee-validate/zodのtoTypedSchemaを使うと、ZodのスキーマをそのままuseFormのvalidationSchemaに渡せます。defineFieldでフィールドとそのv-bind用属性を同時に取得できるのもポイントです。
import { useForm } from 'vee-validate'
import { toTypedSchema } from '@vee-validate/zod'
import { z } from 'zod'
const schema = toTypedSchema(
z.object({
username: z.string().min(3, '3文字以上で入力してください'),
age: z.coerce.number().int().min(18, '18歳以上である必要があります'),
})
)
const { defineField, errors } = useForm({ validationSchema: schema })
const [username] = defineField('username')
ユーザー名を2文字以下にしたり、年齢を17以下にすると、Zod側で定義したmin()のエラーメッセージがそのまま表示されます。スキーマ検証のロジックをZodに寄せつつ、フォームの状態管理はVee-Validateに任せる分担ができるのがこのパターンの利点です。
Form・Fieldコンポーネントによる宣言的な記述
Composition APIを書かずに、テンプレートだけでバリデーションを組みたい場合はForm・Field・ErrorMessageコンポーネントを使います。Fieldのrulesにバリデーション関数を渡すだけで、useFieldを明示的に呼ばなくても同じ検証ができます。
<script setup>
import { Form, Field, ErrorMessage } from 'vee-validate'
function validatePassword(value) {
if (!value) return 'パスワードは必須です'
if (value.length < 8) return '8文字以上で入力してください'
return true
}
</script>
<template>
<Form @submit="(values) => console.log(values)">
<Field name="password" type="password" :rules="validatePassword" />
<ErrorMessage name="password" />
</Form>
</template>
パスワードを8文字未満に書き換えると、Fieldが内部でuseFieldを呼び出して検証し、ErrorMessageがそのエラーを表示します。useFormやuseFieldを自分で呼ばなくても、Fieldのname属性だけでフォームの状態管理に組み込まれる点がこのパターンの特徴です。
useFieldArrayによる動的なフィールド
「メンバーを何人でも追加できる」「注文明細を自由に増減できる」といった可変長の入力には、useFieldArrayを使います。配列の各要素が独立したフィールドとして扱われ、push・removeで要素を追加・削除できます。
import { useFieldArray } from 'vee-validate'
const { fields, push, remove } = useFieldArray('members')
push({ name: '' }) // 末尾に要素を追加
remove(0) // 先頭の要素を削除
「メンバーを追加」ボタンを押すと入力欄がその場で増え、「削除」ボタンで個別に取り除けます。fieldsの各要素はfield.keyという安定したキーを持つため、v-forで要素の並び替えや削除が起きても、Vueが正しく差分更新できます。
まとめ
Vee-Validateは、useFormとuseFieldというシンプルな2つの関数を軸に、Vueのフォームバリデーションを一箇所にまとめられるライブラリです。関数ルールで手軽に始めることもできれば、ZodやYupのスキーマに寄せて型安全性を高めることもでき、Form・Fieldコンポーネントでテンプレート中心に書くこともできます。useFieldArrayまで含めると、単純な入力チェックから可変長の複雑なフォームまで、同じ考え方で対応できるのが強みです。
まずはuseFieldひとつだけの小さなフォームから試してみて、必要になったタイミングでスキーマ連携やFieldコンポーネントに置き換えていくのがおすすめです。
