如何手動執行所有 VeeValidate 驗證 ?
栏目: JavaScript · 发布时间: 7年前
内容简介: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 欄位,只有第一個欄位輸入正確,第二個欄位尚未輸入,因此其
inputevent 未被觸發,所以 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 才會動態擁有
$validatorproperty,因此要借用Object.prototype.hasOwnProperty()判斷是否有$validatorproperty,才能繼續執行validate() - 因為 component 還會包含其他 component,因此要使用 Recursive,才能對所有 component 進行驗證
Sample Code
完整的範例可以在我的 GitHub 上找到
Reference
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 如何监视 WPF 中的所有窗口,在所有窗口中订阅事件或者附加 UI
- 将所有类定义为Scala中的情况,只是让所有参数自动生成属性是否正确?
- Python捕获所有异常
- 一次解决所有代理问题
- 让所有代码都经过检查
- Rust的所有权
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法心得:高效算法的奥秘(原书第2版)
(美)Henry S. Warren, Jr. / 爱飞翔 / 机械工业出版社 / 2014-3 / 89.00
【编辑推荐】 由在IBM工作50余年的资深计算机专家撰写,Amazon全五星评价,算法领域最有影响力的著作之一 Google公司首席架构师、Jolt大奖得主Hoshua Bloch和Emacs合作创始人、C语言畅销书作者Guy Steele倾情推荐 算法的艺术和数学的智慧在本书中得到了完美体现,书中总结了大量高效、优雅和奇妙的算法,并从数学角度剖析了其背后的原理 【读者评价......一起来看看 《算法心得:高效算法的奥秘(原书第2版)》 这本书的介绍吧!