如何手動執行所有 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

如何手動執行所有 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


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

查看所有标签

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

Beginning ARKit for iPhone and iPad

Beginning ARKit for iPhone and iPad

Wallace Wang / Apress / 2018-11-5 / USD 39.99

Explore how to use ARKit to create iOS apps and learn the basics of augmented reality while diving into ARKit specific topics. This book reveals how augmented reality allows you to view the screen on ......一起来看看 《Beginning ARKit for iPhone and iPad》 这本书的介绍吧!

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

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具