Vue 3 + TypeScript(Composition API)で、シンプルなユーザー登録フォームの例を作ります。
バリデーションも少し入れておきます。
ソースコード
UserForm.vue
<template>
<form @submit.prevent="handleSubmit">
<div>
<label>苗字</label>
<input v-model="form.lastName" type="text" />
</div>
<div>
<label>名前</label>
<input v-model="form.firstName" type="text" />
</div>
<div>
<label>性別</label>
<label>
<input type="radio" value="male" v-model="form.gender" />
男性
</label>
<label>
<input type="radio" value="female" v-model="form.gender" />
女性
</label>
</div>
<div>
<label>メールアドレス</label>
<input v-model="form.email" type="email" />
</div>
<div>
<label>パスワード</label>
<input v-model="form.password" type="password" />
</div>
<div>
<label>都道府県</label>
<select v-model="form.prefecture">
<option value="">選択してください</option>
<option value="東京都">東京都</option>
<option value="埼玉県">埼玉県</option>
<option value="神奈川県">神奈川県</option>
<option value="千葉県">千葉県</option>
</select>
</div>
<div>
<label>
<input type="checkbox" v-model="form.isAdmin" />
管理者
</label>
</div>
<button type="submit">登録</button>
</form>
<pre>{{ form }}</pre>
</template>
<script setup lang="ts">
import { reactive } from "vue";
type Gender = "male" | "female" | "";
interface UserForm {
lastName: string;
firstName: string;
gender: Gender;
email: string;
password: string;
prefecture: string;
isAdmin: boolean;
}
const form = reactive<UserForm>({
lastName: "",
firstName: "",
gender: "",
email: "",
password: "",
prefecture: "",
isAdmin: false,
});
const validate = (): string[] => {
const errors: string[] = [];
if (!form.lastName) errors.push("苗字は必須です");
if (!form.firstName) errors.push("名前は必須です");
if (!form.gender) errors.push("性別を選択してください");
if (!form.email.includes("@")) errors.push("メールアドレスが不正です");
if (form.password.length < 6)
errors.push("パスワードは6文字以上にしてください");
if (!form.prefecture) errors.push("都道府県を選択してください");
return errors;
};
const handleSubmit = () => {
const errors = validate();
if (errors.length > 0) {
alert(errors.join("\n"));
return;
}
console.log("送信データ:", form);
alert("登録完了!");
};
</script>
<style scoped>
form {
max-width: 400px;
}
div {
margin-bottom: 10px;
}
label {
display: block;
}
</style>
解説
●reactive + TypeScript interface で型安全に管理
●v-modelで双方向バインディング
●ラジオボタン・チェックボックス・セレクトすべて対応
●簡易バリデーション付き
サイト
Vue Playground
Vuetify Playground