填寫表單時,需要驗證是否必填(require)、或是格式是否正確,自己手刻很複雜,可能也會不夠全面,用套件來做驗證是最省事又快速的。在 Vue2 框架時,我偏好使用 vee-validate 來做驗證,因為它簡單又好用,但到了 Vue3,veeValidate4 怎麼好像是另一個世界惹😱,vee-validate4 該怎麼使用呢
安裝 vee-validate
首先先安裝 vee-validate
1 2 3
| yarn add vee-validate # or npm i vee-validate --save
|
另外 yup 也是個簡單卻強大的驗證 library,vee-validate 可以結合 yup 一起使用
安裝 yup
1 2 3
| yarn add yup # or npm i yup --save
|
使用 vee-validate
vee-validate 提供了兩種方法,可以使用 components 或是 composition API
components: 適合簡單的 UI 組件和具有自定義樣式的原生 HTML 元素,使用 Field、Form 和 ErrorMessage
composition API: 適合構建複雜的 UI 表單組件和通用數據驗證,使用 useField、useForm
這兩種方式都可以混合使用
我這邊使用的是 composition API + yup 來做驗證
製作需求:
1.取得 API 資料後,會自動把資料帶入到表單
2.表單驗證
3.取得表單值
在 main.js 引入全局 (global) 驗證、表單 component input,如果表單只有一頁,可以直接引用在表單頁面
main.js
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { createApp } from 'vue' import App from './App.vue' import router from './router'
const app = createApp(App);
import { schema } from '@/utils/validate.js'; app.provide('schema', schema); import FormInput from '@/components/FormInput.vue'; app.component('FormInput', FormInput);
app.use(router).mount('#app')
|
用 yup 處理驗證格式的 js
.required 必填
.matches 客製驗證格式
.oneOf 確認 key 是否相同
.min 最少幾位數
.max 最多幾位數
.nullable 接受 key 為 null
utils/validate.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import { object, string, ref, array } from 'yup'; const required = '必填'; const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/; const passwordRegExp = /[a-zA-Z0-9]/;
export const schema = object().shape({ email: string().required(required).email('E-mail輸入錯誤'),
password: string() .required(required) .min(8, '密碼最少8位') .max(20, '密碼最多20位') .matches(passwordRegExp, '請輸入不含符號的半形英文、數字'),
confirmPassword: string() .oneOf([ref('password')], '輸入密碼不相同') .required(required),
phone: string().matches(phoneRegExp, '手機輸入錯誤'),
userName: string().nullable().required(required),
link: array().of(string().required('請輸入標題')), });
|
設定從父層來的 props
components/FormInput.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <template> <input :id="id" v-model="inputValue" :name="name" :type="type" :placeholder="placeholder" :maxlength="maxlength" class="form-control" :class="{ 'is-invalid': errorMessage }" /> <div class="invalid-feedback">{{ errorMessage }} </div> </template>
|
並設定 useField 的值 (value) 跟錯誤訊息 (errorMessage),會由 name 來判定驗證格式是否正確,watch 是為了取得 API 資料後,會自動把資料帶入到表單,如沒有這個需求可以拿掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import { useField } from 'vee-validate'; import { watch } from 'vue';
export default { props: { name: { type: String, required: true, }, id: { type: String, default: '', }, type: { type: String, default: '', }, modelValue: { type: String, default: '', }, placeholder: { type: String, default: '', }, maxlength: { type: Number, default: Infinity, }, }, setup(props) { let { value: inputValue, errorMessage } = useField( props.name, undefined, { initialValue: props.modelValue, } );
watch( () => props.modelValue, val => { inputValue.value = val; } );
return { inputValue, errorMessage, }; }, };
|
表單頁面
插入 input component,設定好要傳入的 props
Form.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| <template> <div class="form-box"> <div> <div class="form-group"> <label for="userName">姓名:</label> <FormInput :id="'userName'" v-model="memberInfo.data.name" :name="'userName'" :type="'text'" :placeholder="'輸入'" /> </div> <div class="form-group"> <label for="password">密碼:</label> <FormInput :id="'password'" v-model="password.password" :name="'password'" :type="'password'" :placeholder="'輸入'" /> </div> <div class="form-group"> <label for="confirmPassword">確認密碼:</label> <FormInput :id="'confirmPassword'" v-model="password.confirmPassword" :name="'confirmPassword'" :type="'password'" :placeholder="'輸入'" /> </div> <div class="form-group"> <label for="email">e-mail:</label> <FormInput :id="'email'" v-model="memberInfo.data.email" :name="'email'" :type="'text'" :placeholder="'輸入'" /> </div> <div> <div v-for="(item, idx) in fields" :key="item.url" class="form-group"> <label :for="`link${idx}`">link{{idx+1}}:</label> <FormInput :id="`link[${idx}]`" :name="`link[${idx}].url`" :type="'text'" :placeholder="'輸入'" /> <button type="button" @click="remove(idx)">remove</button> </div> <button type="button" @click="push({url: ''})">add</button> </div> </div> </div> <div> Form 表單取值: {{ values }} </div> </template>
|
設定 useForm、useFieldArray
useForm 是整個 Form 表單,設定驗證並取值,取到的值 submit 到後端,就資料完成送出啦!
useFieldArray 用來設定陣列的 input,可使用內建方法:移除 (remove)、取代 (replace)、新增資料 (push)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import { reactive, inject } from 'vue'; import { useForm, useFieldArray } from 'vee-validate'; import axios from 'axios';
export default { setup() { const schema = inject('schema');
const { values } = useForm({ validationSchema: schema, });
const { replace, remove, push, fields } = useFieldArray('link');
const password = reactive({ password: '', confirmPassword: '', });
const publicPath = process.env.BASE_URL; const getMemberInfo = () => { return axios.get(`${publicPath}data/info.json`); };
let memberInfo = reactive({ data: {} });
getMemberInfo().then(res => { memberInfo.data = res.data; replace(memberInfo.data.link); });
return { password, memberInfo, values, remove, push, fields } } }
|
1 2 3 4 5 6 7 8 9 10 11
| .form-box { display: flex; justify-content: center; align-items: center; height: 100%; }
.form-group { margin: 20px 0; display: flex; }
|
資料格式
data/info.json
1 2 3 4 5 6 7 8
| { "name": "bobee", "email": "lala9990929@gmail.com", "link": [ { "url": "https://happy9990929.github.io"}, { "url": "https://happy9990929.github.io/gtplay"} ] }
|
結語
vee-validate4.0 跟之前的版本差異真的很大,我也是研究了一陣子,如果有哪邊有問題或是有更好的寫法,歡迎路過的大大指正噢🧐
👉 附上我的 vee-validate4 範例
最後用可愛的 bobee 做結尾吧!
參考文獻
vee-validate 官方
🚀實體工作坊分享
最近時賦學苑開了實體體驗課,即使你對程式碼沒有概念也能上手!Lala 會帶你一起做出一個個人品牌形象網站,帶你快速了解前端的開發流程,快跟我們一起玩轉 Web 吧!
🚀線上課程分享
線上課程可以加速學習的時間,省去了不少看文件的時間XD,以下是我推薦的一些課程
想學習更多關於前後端的線上課程,可以參考看看。
Hahow 有各式各樣類型的課程,而且是無限次數觀看,對學生或上班族而言,不用擔心被時間綁住
如果你是初學者,非常推薦六角學院哦!
剛開始轉職也是上了六角的課,非常的淺顯易懂,最重要的是,隨時還有線上的助教幫你解決問題!
Udemy 裡的課程非常的多,品質普遍不錯,且價格都滿實惠的,CP值很高!
也是很多工程師推薦的線上課程網站。