vee-validate 的版本別
vee-validate 經過多個 Vue.js 核心做為相賴套件,而 vee-validate 此套件目前分別對應了 Vue.js 2 與 3 的核心來使用。
在官方文件 https://vee-validate.logaretm.com 都是列出最新的 vee-validate 套件相關說明,只要在網址後方帶上 /v4 或是 /v3 就可以前往對應的套件版別的說明文件。
如果還分不太清楚對應 vue.js 核心版本別,在 vee-validate npm 官方說明 Vue version support 上有列出。
The main v4 version supports Vue 3.x only, for previous versions of Vue ( v4 主版本僅支持 Vue 3.x,對於之前的 Vue 版本 )
在 vee-validate 2~3 的套件版別上,在搬遷上也有些細節要處理,參考文件 vee-validate Migration Guide。
接著下面會以 竹白記事本 – Vue筆記 – 表單驗證套件 VeeValidate 的方式了解 2x 與 3x 的差別。
vee-validate v3 (支援 vue.js 2x 與 3x)
vee-validate 預設 mail 規則驗証
See the Pen Untitled by Jimmy_Wu (@Jimmy_Wu) on CodePen.
via script tag (CDN) 與 ES6+ (建構工具處理) 的二種引用 vee-validate 核心方式差別
vee-validate V3 文件 Getting Started > Usage 有分成 via script tag 與 ES6+ 二種方式引入 vee-validate V3 核心模組的二種引入方式。
via script tag 與 ES6+ 二種使用方式有些差別,使用 CDN 方式將 via script tag 核心引入,會是直接賦予在 VeeValidate 變數下,而使用 ES6+ 方式是專門用於建構工具下處理核心模組,不會賦予 VeeValidate 變數直接取用核心內的模組。
例如使是使用 ValidationObserver 模組,以 via script tag 講 CDN 引入時宣告成 vue.js 2 的全城元件,就需要以 Vue.component('ValidationObserver', VeeValidate.ValidationObserver); 使用。
連接符轉換駝峰命名:vue 元件小駝峰名稱與直接在 HTML Tag 下的
Basic Example 提到,在存 JS 環境下使用元件或是 Vue 樣版,會是直接以小駝峰的方式來使用,而如果是直接應用在 HTML Tag 下會需要將駝峰寫法改 - 連接,在 Vue 進入組件會轉換成小駝峰命名。
VeeValidate.extend 擴充功能方法,引入所有 rules 驗証方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | console.log('VeeValidate.extend', VeeValidate.extend) import * as rules from "https://cdnjs.cloudflare.com/ajax/libs/vee-validate/3.4.13/rules.min.js"; Object.keys(rules).forEach((rule) => { VeeValidate.extend(rule, rules[rule]); }); Vue.component("validation-provider", VeeValidate.ValidationProvider); new Vue({ el: "#app", data: { user: { email: "" } } }); |
- VeeValidate.extend 確任擴充方法啟用。
- import * as rules from 'rules.min.js' 將所有驗証方法全部匯入在 rules 物件下。
- Object.keys(rules).forEach((rule) => { VeeValidate.extend(rule, rules[rule]); }); 所有驗証方法包在 rules 物件,以回圈方式執行 VeeValidate.extend(),所有規則遂一加入擴充中。
- Vue.component("validation-provider", VeeValidate.ValidationProvider); 指定 ValidationProvider 的元素,擣載到全域中使用,讓所有 Vue 的元件都可引入使用。
1 2 3 4 5 6 7 8 9 | <div id="app" class="container"> <div class="row my-2"> <validation-provider class="col-6 mb-3" tag="div" v-slot="{ failed, errors }" rules="required|email"> {{ errors }} <input class="form-control" type="email" name="Email" v-model="user.email" placeholder="輸入 email 格式" /> <span class="text-danger" v-if="failed">{{ errors[0] }}</span> </validation-provider> </div> </div> |
- validation-provider 使用 VeeValidate.ValidationProvider 的方式,設定在 Vue 的全域元件。
- tag="div":指定虛擬的元素,預設會是以行內元素 spna 呈現。
- v-slot="{ failed, errors }": failed 與 errors 傳入元件中,當驗証錯誤發生時會觸發 errors 產生 failed 物件。
- rules="required|email" 屬性是由 js 的 extend(rule, rules[rule]) 所引入証驗方式,這是官方提供的驗証規則,其中包括了 required 必填與 emial 的驗証規則等方式,指定在此元件中要使用的規則。
- failed 是 extend(rule) 引入官方提供的驗証規則的其中一個設定,也啷有這樣的引入方式才會有這樣的設定。
- {{ errors }} 印出在元件內產生的錯誤物件內容。
- name="Email" 在產生錯誤物件時會產生 {field} 屬性,對應整個元件下的名稱,沒設定的話會回應出 {field} 做為開頭,可直接將中文字串內容做為元件驗証產生的錯誤物件為 name 使用。
自定驗証
value >= 5 的 JS 判斷式回傳布林值,決定產生的錯誤物件 errors 直接操作 DOM 元素
接下來是要將 input 元素,透過自已的規劃的 JS 判斷式將取得的值來驗証。
See the Pen vee-validate 3 CDN 基本引用方式 by Jimmy_Wu (@Jimmy_Wu) on CodePen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | const { extend, ValidationProvider } = VeeValidate; console.log("VeeValidate.extend", extend); import * as rules from "https://cdnjs.cloudflare.com/ajax/libs/vee-validate/3.4.13/rules.min.js"; Object.keys(rules).forEach((rule) => { extend(rule, rules[rule]); }); extend("positive", (value) => value >= 5); extend("positiveValue_error", (value) => false); extend("positiveValue_sucss", (value) => true); Vue.component("validation-provider", ValidationProvider); new Vue({ el: "#app", data: { positiveValue: "", positiveValue_error: "", positiveValue_sucss: "" } }); |
- extend("positive", (value) => value >= 5);:宣告出一個 positive 的自定義規則出來,其他二個 positiveValue_error 與 positiveValue_sucss 規則,在處理驗証 value 的結果回傳出來的布林值,決定比較的結果會不會觸發 errors 錯誤物件。
- failed 是 extend(rule) 引入官方提供的驗証規則的其中一個設定,在自定驗証方式下不需也沒有這樣的設定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <div id="app" class="container"> <div class="row my-2"> <Validation-provider class="col-md mb-3" tag="div" rules="positive" v-slot="{ errors }"> <input class="form-control" v-model="positiveValue" type="text" placeholder=">= 5 (自定 vee-validate 自定驗証規則証方式)" name="自定驗証規則" /> <span class="text-danger" v-if="errors[0]">{{ errors[0] }}</span> </Validation-provider> <Validation-provider class="col-md mb-3" tag="div" rules="positiveValue_error" v-slot="{ errors }"> <input class="form-control" v-model="positiveValue_error" type="text" placeholder="false (自定 vee-validate 驗証規則回傳 false 都會是回應錯誤)" name="自定驗証規則_false" /> <span class="text-danger" v-if="errors[0]">{{ errors[0] }}</span> </Validation-provider> <Validation-provider class="col-md mb-3" tag="div" rules="positiveValue_sucss" v-slot="{ errors }"> <input class="form-control" v-model="positiveValue_sucss" type="text" placeholder="true (自定 vee-validate 驗証規則回傳 true 都會是回應正確)" name="自定驗証規則_sucss" /> <span class="text-danger" v-if="errors[0]">{{ errors[0] }}</span> </Validation-provider> </div> </div> |
- 所有輸入的在 input 元素中的值,透過 v-slot="{ errors }" 將錯誤物件插入元件中回應出來。
- 元件驗証結果取決於 extend("positiveValues", (value) => value >= 5); 第二個 callback function,當回傳出來的是 false 就會產生出 errors 物件。
- v-if="errors[0]" 決定印錯誤的 DOM 元素,當然也可以不使用 v-if 會一直呈現在畫面的結構中。
以正規表達式,製作密碼需至少 8 碼以上,並英文數字混合驗証
See the Pen vee-validate 3 自定驗証規則 by Jimmy_Wu (@Jimmy_Wu) on CodePen.
1 2 3 4 5 6 7 8 9 10 11 12 13 | const { extend, ValidationProvider } = VeeValidate; extend("en_num_min8_reg", (value) => { const EnNumREG = /^(?=.*\d)(?=.*[a-zA-Z]).{8,30}$/; let useEnNumREG = new RegExp(EnNumREG); return useEnNumREG.test(value) ? true : "密碼需至少 8 碼以上,並英文數字混合"; }); Vue.component("validation-provider", ValidationProvider); let vm = new Vue({ el: "#app", data: { en_num_min8_reg: "" } }); |
- 以正規表達試 /^(?=.*\d)(?=.*[a-zA-Z]).{8,30}$/ 訂定判斷格式,參考保哥-使用 Regular Expression 驗證密碼複雜度 規劃。
- extend() 方法加入証證規則,此例是直接使用函式,另外一種方式是第二參數 validate ( VeeValidate.extend("veePositiveInteger", { validate: (value) => { let reg = /^[1-9][0-9]*$/; return reg.test(value) ? true : "請輸入一個正整數" }, });) 規劃判斷方式。
1 2 3 4 5 6 7 8 | <div id="app" class="container"> <div class="row my-2"> <validation-provider class="col mb-3" tag="div" v-slot="{ errors }" rules="en_num_min8_reg"> <input class="form-control" type="text" name="中英文混合輸入內容" v-model="en_num_min8_reg" placeholder="輸入中英文混合輸入內容" :class="{ 'is-invalid': errors[0] }" /> <span class="text-danger" v-if="errors[0]">{{ errors[0] }}</span> </validation-provider> </div> </div> |
- v-slot="{ errors }" 將錯誤資訊以插槽,將錯誤資訊傳入元件中。
- :class="{ 'is-invalid': errors[0] } 判斷資料是否回傳出錯誤。
- rules="en_num_min8_reg" 指定使用自訂的驗証格式。
- <span class="text-danger" v-if="errors[0]">{{ errors[0] }}</span> 在產生出錯誤時,會在 DOM 元素中產生結果。
vee-validate v4 (支援 vue.js 3x)
簡易使用與宣告成 vue 3 全域元件
See the Pen vee-validate 3 自定驗証規則 (密碼需至少 8 碼以上,並英文數字混合) by Jimmy_Wu (@Jimmy_Wu) on CodePen.
1 2 | <script src="https://unpkg.com/vue@next"></script> <script src="https://unpkg.com/vee-validate"></script> |
引入新版的 Vue 3x 與 vee-validate 驗証套件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | const App = { components: { VForm: VeeValidate.Form, VField: VeeValidate.Field, ErrorMessage: VeeValidate.ErrorMessage }, methods: { isRequired(value) { if (!value) { return "this field is required"; } return true; }, onSubmit(values) { alert(JSON.stringify(values, null, 2)); } } }; Vue.createApp(App).mount("#app"); |
- VeeValidate.Form、 VeeValidate.Field、 VeeValidate.ErrorMessage 分別由 CDN 的 vee-validate 引入相關核心方法,包裝在 Vue 實體全域元件。
- 判斷驗証的規則,包裝在 Vue 實體下的 isRequired(value) {} 方法下,等待 HTML 樣版在 input 輸入資料時,
- onSubmit(values){} 函式方法,是直接將要傳送出去的 form 表單,將要傳出去的值轉成 JSON 格式。
1 2 3 4 5 6 7 | <div id="app"> <v-form @submit="onSubmit"> <v-field name="name" type="text" placeholder="Who are you" :rules="isRequired"></v-field> <error-message name="name"></error-message> <button>Submit</button> </v-form> </div> |
- 因為是使用自訂的方式,所以傳入判斷驗証的函式 :rules="isRequired",要加上 : 做為動態傳入到元件中。
- 原本的 input 元素替換成的 <v-field><v-field>,特別留意結尾標籤。
- <v-form @submit="onSubmit"></v-form> 內包的 <button>Submit</button> 按鈕元件,直接以 @submit="onSubmit" 執行送出表單行為,直接觸發 Vue 實體下 onSubmit(values) {} 方法。
完整與自定義驗証表單、設定繁中語系
See the Pen vee-validate 4 (完整驗証表單) by Jimmy_Wu (@Jimmy_Wu) on CodePen.
引入相關 CDN ,以下要特別指定套件版本別
1 2 3 4 | <script src="https://unpkg.com/vue@next"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vee-validate/4.1.17/vee-validate.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@vee-validate/i18n@4.1.17/dist/vee-validate-i18n.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@vee-validate/rules@4.1.17/dist/vee-validate-rules.min.js"></script> |
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 | /** 資料 * 表單驗證套件 vee-validation 課程文件 (https://hackmd.io/FFv0a5cBToOATP7uI5COMQ) * 官方語系文件 (https://vee-validate.logaretm.com/v4/guide/i18n#localizing-field-names) */ // console.log('Vue', Vue); // console.log('VeeValidate.useField', VeeValidate.useField); const { Form, Field, ErrorMessage, defineRule, configure } = VeeValidate; // console.log('Form, Field, ErrorMessage', Form, Field, ErrorMessage) // console.log('defineRule', defineRule) /* VeeValidate 載入規則模組,加入到 Vue 的 defineRule() */ // console.log('VeeValidateRules', VeeValidateRules) Object.keys(VeeValidateRules).forEach((rule) => { if (rule !== 'default') { defineRule(rule, VeeValidateRules[rule]); } }); /* VeeValidate 繁體中文化 */ // console.log('VeeValidateI18n', VeeValidateI18n) const { localize, loadLocaleFromURL } = VeeValidateI18n; // 讀取外部的資源 loadLocaleFromURL( 'https://unpkg.com/@vee-validate/i18n@4.1.0/dist/locale/zh_TW.json' ); configure({ generateMessage: localize('zh_TW', {}), validateOnInput: true, // 調整為:輸入文字時,就立即進行驗證 }); const app = Vue.createApp({ data() { return { user: { email: '', name: '', address: '', phone: '', }, }; }, methods: { onSubmit() { console.log('onSubmit() this.user', this.user); }, isPhone(value) { const phoneNumber = /^(09)[0-9]{8}$/; // return phoneNumber.test(value) return phoneNumber.test(value) ? true : '需要正確的電話號碼'; }, }, }); // VeeValidate 註冊成 Vue 的全域元件 app.component('VForm', Form); app.component('VField', Field); app.component('ErrorMessage', ErrorMessage); app.mount('#app'); |
- VeeValidateRules 語 CDN 引入,配合 Object.keys(VeeValidateRules).forEach((rule) => {}) 執行迴圈,而在判斷式在模組 'default' 進行排除,如果直接使用會回傳出錯誤。
- VeeValidateI18n 引入多國語系插件, const { localize, loadLocaleFromURL } = VeeValidateI18n; 使用物件解構取得二個套件方法。
- 使用 loadLocaleFromURL() 外部引入方式加入繁中的 JSON 檔。
- configure() 方法設定多過語系,在屬性 generateMessage: localize('zh_TW', {}), 指定使用 'zh_TW' 繁中語系。
- validateOnInput: true, 設定,在立即輸入資料到 input 元素後,會直接進行驗證,預設是不會直接觸發。
- isPhone(value) {} 做為傳入元件中,之後會在 HTML 結構屬性 :rules="isPhone" 將規則傳入元件。
- app.component('VForm', Form);、 app.component('VField', Field);、 app.component('ErrorMessage', ErrorMessage); 在 vee-validate CDN 解出元件,並透過 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 64 65 66 67 68 69 | <div id="app"> <div class="container"> <v-form v-slot="{ errors }" @submit="onSubmit" > {{ errors }} <div class="mb-3"> <label for="電子郵件" class="form-label">電子郵件</label> <v-field id="email" name="電子郵件" type="email" class="form-control" :class="{ 'is-invalid': errors['電子郵件'] }" placeholder="請輸入電子郵件" rules="email|required" v-model="user.email" ></v-field> <error-message name="電子郵件" class="invalid-feedback" ></error-message> </div> <div class="mb-3"> <label for="地區" class="form-label">地區</label> <v-field id="name" name="地區" class="form-control" :class="{ 'is-invalid': errors['地區'] }" placeholder="請輸入地區" rules="required" v-model="user.region" as="select" > <option value="">請選擇地區</option> <option value="台北市">台北市</option> <option value="高雄市">高雄市</option> </v-field> <error-message name="地區" class="invalid-feedback"></error-message> </div> <div class="mb-3"> <label for="tel" class="form-label">電話</label> <v-field id="tel" name="手機號碼" type="text" class="form-control" :class="{ 'is-invalid': errors['手機號碼'] }" placeholder="請輸入手機號碼" :rules="isPhone" v-model="user.phone" ></v-field> <error-message name="手機號碼" class="invalid-feedback" ></error-message> </div> <button class="btn btn-primary" type="submit" :disabled="(Object.entries(errors).length > 0) ? true : false" > 送出表單 </button> </v-form> </div> </div> |
- <v-form></v-form> 元件標籤、 v-slot="{ errors }" 將裡面所有的表單元件所產生的錯誤傳入。
- @submit="onSubmit" 在 Vue 實體下的點按事件方法,配合傳入的錯誤長度判斷,在所有輸入框一定都要通過才能點按送出,而表單只也只有一個 <button type="submit">送出表單</button> 做為執行 onSubmit 方法的動態元件對象。
- 所有的 <v-field> 元件,都是做為 input 元素的替換對象,都需加上標籤結尾。
- 電子郵件的 rules="email|required"、地區選擇 rules="required" 的証驗規則,都是官方所提拱的驗証規則。
- 所有的 <error-message> 是由 JS 解構出來的 ErrorMessage 模組方法,在產生錯誤物件時會在此元件呈現出 DOM 結構。
- 手機號碼元件 :rules="isPhone" 以動態傳入的方式,將 Vue 實體下的方法傳入元件中。