Vee-Validate 4 表單驗證簡單上手

在開發中驗證表單欄位是一件前後端都必須處理的事情,不僅前端要驗證使用者輸入的欄位資訊,後端也要驗證送往伺服器的資料。

而前端的驗證如果要自己寫,會牽扯到正則,而且也會容易掛一漏萬,所以如果要在 Vue 裡面進行表單驗證,通常會引用套件,但是並不是所有的套件都支援中文語系。

Vee-Validate 是目前比較完整而且支援繁體中文語系的驗證套件。雖然說是套件,如果你去看 Vee-Validate 的官網,保證看完了,還是一頭霧水。所以我整理了 Vee-Validate 的使用方法,以防自己下次要用又失憶了。

Vee-Validate 官網:https://vee-validate.logaretm.com/v4/

因為目前我所使用的是 Vue 3 的版本,所以要搭配 Vee-Validate 4.0 以上版本,在安裝的時候要注意版本相匹配的問題。

安裝 Vee-Validate

安裝時除了 Vee-Validate 主程式之外,還要安裝驗證規則(rules)及多國語系(i18n)。

npm i vee-validate @vee-validate/i18n @vee-validate/rules @vee-validate/i18n --save

只要在 main.js 中設定,多國語系(i18n)就會把驗證的錯誤訊息轉成繁體中文。

例如: “email”: “{field} 須為有效的電子信箱”, {field} 的部分會填入對應的欄位名稱。

繁體中文驗證顯示內容

main.js 設定

在 main.js 中引入套件之外,同時把相關的規則及元件做全域註冊,就不用在每個需要做驗證的 vue 檔案中一一匯入。

import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";

// 匯入 vee-validate 主套件
import { Field, Form, ErrorMessage, defineRule, configure } from "vee-validate";

// 匯入 vee-validate 相關規則
import {
  required,
  email,
  min,
  numeric,
  max_value,
  min_value,
  between,
  digits
} from "@vee-validate/rules";
// import * as rules from '@vee-validate/rules';

// 匯入多國語系的功能
import { localize, setLocale } from "@vee-validate/i18n";

// 匯入繁體中文語系檔案
import zhTW from "@vee-validate/i18n/dist/locale/zh_TW.json";

const app = createApp(App);

// 定義驗證規則
defineRule("required", required);
defineRule("email", email);
defineRule("min", min);
//  數字,但是小數點會認為是非數字
defineRule("numeric", numeric);
defineRule("max_value", max_value);
defineRule("min_value", min_value);
// between 可以驗證 某個區間的數字,例如 5~10
defineRule("between", between);
// digits 限制小數點後幾位數
defineRule("digits", digits);

// 設定 vee-validate 全域規則
configure({
  generateMessage: localize({ zh_TW: zhTW }), // 載入繁體中文語系
  validateOnInput: true, // 當輸入任何內容直接進行驗證
});

// 設定預設語系
setLocale("zh_TW");

// 註冊 vee-validate 三個全域元件
app.component("Form", Form);
app.component("Field", Field);
app.component("ErrorMessage", ErrorMessage);

app.mount("#app");

也可以使用這種方法把全部的規則都引入,就不用像上面一樣一一定義驗證規則。

import { defineRule } from 'vee-validate';
import * as rules from '@vee-validate/rules';

Object.keys(rules).forEach(rule => {
  defineRule(rule, rules[rule]);
});

表單欄位的設定

表單的頭尾要用大寫 F 開頭的 <Form> 包住, v-slot=”{ errors }” 則對應到錯誤訊息欄位。

<Form ref="form" @submit="submitOrders" v-slot="{ errors }">
</Form>

原本的 <input>Z標籤用 標籤取代, 其中 name 會對應到 name,如果欄位輸入錯誤,以 email 欄位為例,就會出現:「email 為必填」。

rules="email|required" 則會去抓 main.js 中定義的表單規則。

:class="{ 'is-invalid': errors['email'] }" 輸入驗證錯誤則會綁定 Bootstrap 中 is-invalid 樣式,讓輸入框的 border 變成紅色的。

<Field id="email" name="email" type="email" class="form-control" rules="email|required" :class="{ 'is-invalid': errors['email'] }" placeholder="請輸入 Email" v-model="form.user.email"></Field>
<ErrorMessage name="email" class="invalid-feedback"></ErrorMessage>

<button>disabled 有綁訂到 Vee-Validate 的 errors 物件,如果陣列長度大於 0,按鈕就不能按。

<button type="submit" class="btn btn-lg w-100 add-btn" @submit="submitOrders" :disabled="Object.keys(errors).length > 0">
      送出訂單
</button>
<Form ref="form" @submit="submitOrders" v-slot="{ errors }">
  <div class="mb-3">
    <label for="email" class="form-label">Email<span class="form-note">*</span></label>
    <Field id="email" name="email" type="email" class="form-control" rules="email|required" :class="{ 'is-invalid': errors['email'] }" placeholder="請輸入 Email" v-model="form.user.email"></Field>
    <ErrorMessage name="email" class="invalid-feedback"></ErrorMessage>
  </div>
  <div class="mb-3">
    <label for="name" class="form-label">收件人姓名<span class="form-note">*</span></label>
    <Field id="name" name="姓名" type="text" class="form-control" :class="{ 'is-invalid': errors['姓名'] }" placeholder="請輸入姓名" rules="required" v-model="form.user.name"></Field>
    <ErrorMessage name="姓名" class="invalid-feedback"></ErrorMessage>
  </div>
  <div class="mb-3">
    <label for="tel" class="form-label">收件人電話<span class="form-note">*</span></label>
    <Field id="tel" name="電話" type="text" class="form-control" :rules="isPhone" :class="{ 'is-invalid': errors['電話'] }" placeholder="請輸入電話" v-model="form.user.tel"></Field>
    <ErrorMessage name="電話" class="invalid-feedback"></ErrorMessage>
  </div>
  <div class="mb-3">
    <label for="address" class="form-label">收件人地址<span class="form-note">*</span></label>
    <Field id="address" name="地址" type="text" class="form-control" :class="{ 'is-invalid': errors['地址'] }" placeholder="請輸入地址" rules="required" v-model="form.user.address"></Field>
    <ErrorMessage name="地址" class="invalid-feedback"></ErrorMessage>
  </div>
  <div class="mb-3">
    <label for="message" class="form-label">留言</label>
    <textarea id="message" class="form-control" cols="30" rows="10" v-model="form.message"></textarea>
  </div>
  <div class="text-end">
    <button type="submit" class="btn btn-lg w-100 add-btn" @submit="submitOrders" :disabled="Object.keys(errors).length > 0">
      送出訂單
    </button>
  </div>
</Form>

Script 中的設定

表單的 v-model 有綁訂到 data 的 form 物件。 button 綁定的 submitOrders 方法是打 API 把訂單送去後端。

data () {
    return {      
      form: {
        user: {
          name: '',
          email: '',
          tel: '',
          address: ''
        },
        message: ''
      },
     
    }
  },

其中手機號碼的驗證規則,也寫在 methods 裡面:

methods: {
    // validate
    isPhone (value) {
      const phoneNumber = /^(09)[0-9]{8}$/
      return phoneNumber.test(value) ? true : '需要正確的電話號碼'
    },      
}

久久寫一次驗證,發覺自己有點失意,寫個筆記,希望下次可以不用花那麼久的時間重新探索。

參考:


Vee-Validate 4 表單驗證簡單上手
https://popeye-ux.github.io/2023/02/18/vue-vee-validate4/
作者
POPEYE
發布於
2023年2月18日
許可協議