如何手動執行所有 VeeValidate 驗證 ?

栏目: JavaScript · 发布时间: 5年前

内容简介: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

如何手動執行所有 VeeValidate 驗證 ?

  1. 兩個 email 欄位,只有第一個欄位輸入正確,第二個欄位尚未輸入,因此其 input event 未被觸發,所以 VeeValidate 尚未執行驗證,按下 Submit 之後,才會對所有欄位進行驗證,並且 alert() 顯示錯誤訊息

如何手動執行所有 VeeValidate 驗證 ?

  1. 啟動 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 大於 1return 不執行。

因為 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.$elquerySelect() 抓到該欄位,然後呼叫 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

VeeValidate , Validation Events


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

设计方法卡牌

设计方法卡牌

罗莎 等 / 电子工业出版社 / 2017-7 / 79.00

本套设计素材提供了54种设计方法,以卡牌的形式展示给读者,每张卡牌包括该设计方法的基本描述、目的、时间成本、工具渠道、使用阶段、操作步骤及其归类属性等信息。在做设计时,可以根据自己的需求进行卡牌的选择和组合,让设计工作更有灵活性和趣味性。同时,依据设计产品属性的不同,卡牌提供了选择设计方法的推荐模板、方法组合模板、产品阶段划分模板,给初学者在做设计时提供一定的理论依据,帮助读者启发设计灵感,剖析设......一起来看看 《设计方法卡牌》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具