VeeValidate@3 (for Vue2) 學習筆記
¶VeeValidate@3 (for Vue2) 學習筆記
這篇適用於 vue2 的使用者,也算是對自己學習的一種整理。
為什麼是 vue2 呢?是因為我目前正在維護這個專案就是 vue2
¶安裝
要注意不要安裝到 4 版 (適用 Vue3)
npm install vee-validate@"<3.0.0" --save |
¶使用
¶引用
在這裡寫的 code,可以直接加在 main.js ,也可以另外寫一支,再加到 main.js 裡。
import Vue from 'vue'; |
¶簡單用法 (針對原生 <input>
)
在這裡特別要介紹它的幾種用法。
做為學習的起點,因為官網文件編排,直接就進功能介紹了。XDD
所以特別想寫一下,之後的進階功能再進官網文件看,就很順暢了。
¶簡單 input 驗證
官網特別有寫的資安小知識 (但我用自己的話詮釋一次)
前端的欄位驗證並不是用來取代後端的欄位驗證,而是前後端都要做。
這麼做並不是重工,前端做的目的是增加 UX ,增強系統對使用者的回饋反㒣。
<input v-validate="'required|email'" name="email" type="text"> |
辨別 name
的屬性當關鍵字判斷是哪個欄位,透過 v-validate
執行要判斷的邏輯,再錯誤訊息傳到 errors
物件 (目前這樣寫,是全域的一個物件)。
example:
初始,沒有錯誤訊息,但是 errors 物件原始長這樣
example:
輸入不符合 email 格式的訊息
example:
編輯過後再刪掉,會出現必填的錯誤訊息
¶用很多個?
如果我們依此類推,會得到什麼結果呢?
<h2>簡單用法</h2> |
兩個欄位,不同規格。errors.itms
會跑兩個錯誤出來。
如果只有一個欄位不符規則,errors.itms
就只有一個錯誤在裡面。
¶錯誤訊息 errors
- Displaying Errors
errors.first(name)
<h2>簡單用法</h2> |
把官網的例子複雜化一下,可以發現 first 的參數,要放的是 input 的 name 就可以取得指定欄位的第一個錯誤
errors.collect([name])
<h2>簡單用法</h2> |
把官網後續的例子也複雜化一下,可以發現 collect 的參數,要放的是 input 的 name 就可以取得指定欄位的所有錯誤
如果在此不指定 name ,錯誤訊息就會這樣呈現
error.all()
這裡出現了一個 error.all()
我就在想「如果 error.collect
的參數要是沒有給,會是什麼?」
做了一個比較
<pre>{{ errors.all("url") }}</pre> |
- errors.all(“url”): 指定 name 的 all 是抓不到任何東西的,表示這裡的參數不是 input 的 name
- errors.collect(): 不指定 name 的 collect 會出現「各欄的所有錯誤」
- errors.all(): 不指定 name 的 all 抓到所有欄位的所有錯誤,並且不分類
這些細部的差異,就是學習的過程必須要做出來的比較唷!^^
¶Flags
就是一些…狀態,因為二進制的關係,所以每一位可以各別定義不同的狀態意義。
Flag 的翻譯可能會看見來自組合語言的「旗標」,這個意思源自海上溝通用的旗語
- touched: 表示該欄位已被 touched 或 focused。
- untouched: 表示該欄位尚未被 touched 或 focused。
- dirty: 表示該欄位已被游標經過。
- pristine: 表示該欄位尚未被游標經過。
- valid: 表示該欄位通過驗證。
- invalid: 表示該欄位未通過驗證。
- pending: 表示該欄位的驗證正在進行中。
- validated: 表示該欄位已經至少通過一次事件驗證或手動使用 validate() 或 validateAll() 驗證過。
- changed: 表示該欄位的值已經被更改(嚴格檢查)。
以上面的簡單例子來說
flags 可以這樣從全域物件中叫出來
<h2>Flags</h2> |
¶驗證觸發 Event
預設是 <input>
,預設是監聽 @input
這個 event。但有時候,它的反應太過敏感,可以改用其它的 event (change
之類的)
¶自訂要觸發的 Event
直接改預設
就是一開始在 main.js 裡的設定
Vue.use(VeeValidate); |
改寫成這樣
Vue.use(VeeValidate, { |
加上第二個參數。
關於 Vue.use 的使用方式,以及第二個參數如何使用,請參考 Plugins - Vue2
逐欄設定
依照每個欄位需要,改變觸發的 Event
<input |
¶關閉驗證觸發的 Event
直接改預設
Vue.use(VeeValidate, { |
逐欄設定
<input name="field" |
¶驗證沒過也要做點什麼…
透過 valid 可以判斷驗證的結果是不是通過驗證。
就可以在沒通過驗證時也可以做點什麼了。
<template> |
export default { |
¶自訂規則
官網後來介紹了規則相關的功能。想要自訂的朋友再去看看
- Syntax
- Rules Parameters
- Rules in practice
- Validation Rules
- Custom Rules
- Inferred Rules
- Error Messages (自訂規則之後的自訂錯誤訊息)
¶多國語系
官網後來介紹了多國語系相關的功能。想要自訂的朋友再去看看
- Localization
¶動態顯示的欄位 (與它的驗證)
- Validating Dynamically Displayed Inputs
- Handling v-if
- Handling v-for
¶測試
¶針對自訂 Vue Component 的用法
- Interaction Modes (要在
<ValidationProvider>
才可以用)
自訂 component 的話有兩種情境。
- 驗證單一欄位
- 驗證整個表單
¶ValidationProvider + input
ValidationProvider
是必要的 component 它包裝了你的 input 並從 scoped slot 提供驗證狀態。
由於 ValidationProvider
使用的是 slot 傳出來的驗證狀態,所以會有相對限制的 scope 有效範圍。
example:
將簡單範例的上下加上 ValidationProvider
增加的
- 要加上使用
v-model
來控制 input 裡的值 (就是 component 的用法。),ValidationProvider 也遵遁這個概念,自己會捕捉元件的v-model
進行驗證。 超級重要 - 在 ValidationProvider 上設定
rules='required|url'
- 在 ValidationProvider 上加上
v-slot="{ errors }"
,這樣的話原本<input>
上的 errors 就變slot
的 errors 了。
減少的
- 不使用
v-validate="'required|url'"
- 不使用全域的 errors。
<template>
2 | <ValidationProvider rules="required|url" v-slot="{ errors }"> |
<script>
9 | import { ValidationProvider } from 'vee-validate'; |
通常,它會變成一個 <span>
<span> |
指定 render
用 tag
屬性,可以指定要繪製成什麼 tag
<ValidationProvider rules="required" tag="div"> |
不 render
<ValidationProvider rules="required" slim> |
slim 的意思是,只渲染第一個子節點
¶Scoped Slot Data
Name | Type | Description |
---|---|---|
errors | string[] |
錯誤訊息的列表。 |
failedRules | [x: string]: string |
失敗規則的映射對象,使用 (rule, message) 的形式作為 (key, value)。 |
valid | boolean | null |
目前的驗證狀態。 |
flags | flags |
flags 物件的狀態。 |
aria | { [x: string]: string } |
用於無障礙性的 aria 屬性的映射對象。 |
classes | { [x: string]: boolean } |
基於驗證狀態設置的類別的映射對象。 |
validate | (e: any) => Promise |
作為事件處理器用於觸發驗證的函式。對於不使用 v-model 的欄位很有用。 |
reset | () => void |
在提供者上重置驗證狀態的函式。 |
¶ValidationProvider + 自訂 component
<ValidationProvider rules="required" v-slot="{ errors }"> |
手動觸發驗證
<ValidationProvider rules="required" ref="myinput" v-slot="{ errors }"> |
export default { |
不用 refs 的方式
直接從 slot 取得 validate 放在 event 裡呼叫。
<ValidationProvider rules="required" v-slot="{ validate, errors }"> |
不用 v-model
的 file 也可以用一樣的方式
<ValidationProvider rules="required" v-slot="{ validate, errors }"> |
¶重構 - Higher Order Component
可以透過 Higher Order Component 的方式「後設」Component 的驗證功能。
生成一個又可以放原本 input 的屬性,也可以放 ValidationProvider 屬性的新元件。
import { withValidation } from 'vee-validate'; |
¶重構 - 包成 Component
連同 ValidationProvider 包起來
¶Validation Observer
(待續…)
¶特別的問題
如果一個 ValidationProvider 要驗證三個 input ,三者填其中一個,就算滿足必填。那怎麼辦?
解決方式是,將三個 input 包成一個 component 並且,露出一組 v-model
驗證是否必填的方式就是驗證它是不是 == null
[1] (沒錯是兩個 =
唷)。
在點擊任何一個 input 時,除了觸發 @input
滿足 v-model
的條件之外,還可以透過 @update:value1
來傳遞出原本就要給的值。