如何手動執行所有 VeeValidate 驗證 ?
栏目: JavaScript · 发布时间: 6年前
内容简介:VeeValidate 雖然在Vue 2.5.17VeeValidate 2.1.2
VeeValidate 雖然在 input
event 就會執行驗證,但實務上可能會需要在 Submit
按下時,重新對所有欄位進行驗證,尤其當 component 又包含其他 component 時,該如何對所有 component 進行驗證呢 ?
Version
Vue 2.5.17
VeeValidate 2.1.2
Scenario
- 兩個 email 欄位,只有第一個欄位輸入正確,第二個欄位尚未輸入,因此其
input
event 未被觸發,所以 VeeValidate 尚未執行驗證,按下 Submit 之後,才會對所有欄位進行驗證,並且alert()
顯示錯誤訊息
- 啟動 VeeValidate 驗證後,顯示錯誤訊息,並且將 focus 顯示在第二個 email 欄位
VeeValidate
demo.vue
<template> <div> <div> <input v-model="customEmail1" v-validate="'required|custom-email'" name="customEmailAddress1" type="text"> </div> <div> <input v-model="customEmail2" v-validate="'required|custom-email'" name="customEmailAddress2" type="text"> </div> <div> {{ errors.first('customEmailAddress1') }} </div> <div> {{ errors.first('customEmailAddress2') }} </div> <div> <button @click="onSubmit">Submit</button> </div> </div> </template> <script> import validator from '../validators/email'; /** VeeValidate */ validator(); /** data */ const data = function() { return { customEmail1: '', customEmail2: '', }; }; /** methods */ /** 產生 showError(),目的在僅執行一次,所以使用 closure 包住 count */ const createShowError = function() { let count = 0; return () => { if (count++) return; alert(this.errors.items[0].msg); const name = this.errors.items[0].field; this.$root.$el.querySelector(`[name=${name}]`).focus(); }; }; /** 執行所有 component 的 validate() */ const validateAll = (component, showFunc) => { if (Object.prototype.hasOwnProperty.call(component, '$validator')) component.$validator.validate() .then(result => result || showFunc()); component.$children .forEach(component => validateAll(component, showFunc)); }; /** Submit Handler */ const onSubmit = function() { const showError = createShowError.call(this); validateAll(this.$root, showError); }; const methods = { onSubmit, }; export default { name: 'demo', data, methods, }; </script>
66 行
const onSubmit = function() { const showError = createShowError.call(this); validateAll(this.$root, showError); };
當 Submit
按下後,執行 onSubmit()
。
使用 createShowError()
產生 showError()
,主要是負責 alert()
顯示 第一個
錯誤訊息,為什麼要使用 call()
並傳入 this
呢 ? 稍後會解釋。
執行 validateAll()
對所有欄位進行驗證,第一個參數傳入 root component,第二個參數 showError()
。
43 行
const createShowError = function() { let count = 0; return () => { if (count++) return; alert(this.errors.items[0].msg); const name = this.errors.items[0].field; this.$root.$el.querySelector(`[name=${name}]`).focus(); }; }
createShowError()
目的是建立 showError()
,並且讓 showError()
只執行 一次
。
使用 Closure 將 count
成為 private variable,每執行一次,就會對 count++
,只要 count
大於 1
就 return
不執行。
因為 count
大於 1
就是 Truthy Value,因此可對 count++
直接判斷。
alert(this.errors.items[0].msg)
VeeValidate 會將 errors
object 放在 this
下,也就是 Vue Instance 下,也由於 Vue 會對 this
改變,因此特別使用 function()
,將來要使用 call()
或 apply()
傳入 Vue 的 instance this
。
雖然 this
是在 Arrow Function 內,但 Arrow Function 內的 this
並不會動態改變,而是隨其 parent scope 固定,也就是會跟 createShowError()
的 this
相同,因此 call()
所傳入的 this
,會一併影響 Arrow Function 的 this
。
所有的 VeeValidate 的錯誤訊息 object 都放在 this.errors.items
array 下,其中的 msg
property 就是錯誤訊息,而 itemrs[0]
第一個錯誤訊息。
const name = this.errors.items[0].field;
由於 VeeValidate 必須使用 HTML 的 name
,因此可使用 field
property 抓到欄位的 name
。
this.$root.$el.querySelector(`[name=${name}]`).focus();
利用 this.$root.$el
的 querySelect()
抓到該欄位,然後呼叫 focus()
。
56 行
const validateAll = (component, showFunc) => { if (Object.prototype.hasOwnProperty.call(component, '$validator')) component.$validator.validate() .then(result => result || showFunc()); component.$children .forEach(component => validateAll(component, showFunc)); };
由於 component 可能包含其他 component,因此第一個參數先傳進 root component,由 root component 向下搜尋其他 component。
VeeValidate 有個特性,若該 component 使用 VeeValidate 的話,會在該 component 動態
加上 $validator
property,也就是 $validator
並不是所有的 component 都有,因此要 借用
Object.prototype.hasOwnProperty()
判斷 component 是否有 $validator
property,若有 $validator
property,則表示該 component 有使用 VeeValidate,可繼續呼叫 $validator.validate()
啟動 VeeValidate 驗證。
值得注意的是: validate()
回傳的是 promise
,也就是 VeeValidate 是以 asynchronous 方式執行所有驗證,必須在非同步驗證完之後,才能判斷驗證是否正確。
由於 component 還有包含其他 component,因此要使用 Recursive 方式呼叫 validateAll()
,才能將所有 component 進行驗證。
Conclusion
- 若要使 function 只執行一次,可使用 Closure 搭配 counter
- 只有使用 VeeValidate 的 component 才會動態擁有
$validator
property,因此要借用Object.prototype.hasOwnProperty()
判斷是否有$validator
property,才能繼續執行validate()
- 因為 component 還會包含其他 component,因此要使用 Recursive,才能對所有 component 進行驗證
Sample Code
完整的範例可以在我的 GitHub 上找到
Reference
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 如何监视 WPF 中的所有窗口,在所有窗口中订阅事件或者附加 UI
- 将所有类定义为Scala中的情况,只是让所有参数自动生成属性是否正确?
- Python捕获所有异常
- 一次解决所有代理问题
- 让所有代码都经过检查
- Rust的所有权
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。