使用vue中的混入mixin優化表單驗證插件

以前寫了一篇介紹在vue項目中,如何使用自定義指令開發表單驗證插件的博客。時隔一個多月的時間,我來更新上一篇文章中所遺留的問題了。這段時間開發的時候使用到了這個表單校驗插件,用起來比較麻煩就不說了,還有較嚴重的缺陷。本身最終仍是抽空把這個插件進行了一些優化,雖然優化的方式和當初本身定下的方向不怎麼相同,可是就使用體驗上來講仍是提升了不少。javascript

1. 實際開發中遇到的問題

在上面的文章中說起了一些表單插件的問題,主要針對的是插件開發自己存在的問題。下面我總結下使用中存在的問題:html

  1. 每一個使用表單校驗的元素都須要添加v-check類名,比較麻煩。
  2. 必須在提交表單按鈕上使用v-checkSubmit指令進行表單校驗,提交函數必須命名爲submit(),並且兩者仍是綁定的。
  3. 沒法在一個組件裏面屢次使用校驗函數,沒法自定義校驗的表單範圍。(嚴重問題)

2. 對問題進行分析

一開始個人目標是按照以前計劃的方向,研究如何使用事件訂閱發佈來實現表單校驗,可是評估以後這種方式會對現有的代碼改動較大,由於我項目已經幾處用了當前的校驗方法,遂放棄這個方向。前端

通過查閱資料和思考,我發現vue自己是沒有直接處理、生成dom元素的api。因此當前的這種方法(根據校驗結果添加類名input-error,並追加錯誤信息元素)雖然不優雅,可是確實最簡單有效的方式了。在這個基礎上針對上面列出的幾個問題,我分別整理了解決的思路:vue

  1. 在自定義指令綁定時,能夠獲取到當前綁定的元素,此時能夠給該元素添加v-check類名。
  2. 使用vue中的mixin,提供一個公共的表單校驗方法。每次須要校驗的時候調用該方法,並返回校驗結果。
  3. 本身定義的公共表單校驗方法能夠接受參數,用來指定校驗範圍。

3. 實現

  • 綁定自定義指令的時候添加v-check
import Vue from 'vue'
export default {
  install: (Vue, options) => {
    Vue.directive('validateParams', {
      inserted: function (el, binding, vNode) {
        /* * 解決辦法只需添加下面這一行代碼便可 * el即爲當前指令綁定的元素,classList.add能夠給元素添加類名 */
        el.classList.add('v-check');

        el.addEventListener('blur', function (event) {
          // ...
        })
      }
    });
  }
}

複製代碼
  • 定義公共的表單校驗方法

如何在vue typescript中使用mixin呢java

// mixin.ts
import { Component, Vue } from 'vue-property-decorator';
@Component({})
export class Demo extends Vue {
  public A: string = 'A';
  public doSomething () {

  }
}
// component
<template>
</template>
<script lang="ts">
import { Component, Vue, Mixins } from 'vue-property-decorator';
import { Demo } from 'mixin.ts';
@Component({})
export class App extends Mixins(Demo) {
  private created() {
    console.log(this.A); // 會打印出A
  }
}
</script>

複製代碼

下面咱們實踐,在表單插件中定義這個被mixin的校驗方法typescript

@Component({})
export class ValidatorMixin extends Vue {
  /* * 定義一個GValidate方法,能夠接受一個元素節點參數 * 參數定義了表單函數校驗的範圍 */
  public GValidate(validateEl?: HTMLElement) {
    // 默認是查找當前組件實例內的.v-check元素,this.$el表示當前組件
    let elements = this.$el.querySelectorAll('.v-check');
    if ( validateEl ) {
      // 有參數時,規定了校驗的範圍
      elements = validateEl.querySelectorAll('.v-check');
    }

    const evObj = document.createEvent('Event');
    evObj.initEvent('blur', true, true);

    if (elements) {
      for (const element of elements) {
        element.dispatchEvent(evObj);
      }
    }
    // 仍是查找.input-error元素,以此來判斷檢驗結果
    let errorInputs = this.$el.querySelectorAll('.input-error');
    if (validateEl) {
      errorInputs = validateEl.querySelectorAll('.input-error');
    }
    // 將校驗的結果返回
    if (errorInputs.length !== 0) {
      return false;
    } else {
      return true;
    }
  }
}

複製代碼

定義了上面的校驗方法以後,能夠將原插件裏面定義v-checkSubmit指令的部分刪除了。segmentfault

4. 優化後的使用

// rules.ts
export const required = (message) => ({
  message,
  required: true
});
export const min = (message, length=3) => ({
  message,
  min: length
})
export const max = (message, length=15) => ({
  message,
  max: length
})
export const pattern = (message, reg) => ({
  message,
  pattern: reg
})

// form.vue
<template>
  <div>
    <div class="form-item" ref="userName">
      <label for="userEmail">用戶名:</label>
      <input id="userEmail" type="text" v-model="userName"
        v-validateParams="[inputNameRequired, inputNameMin, inputNameMax, inputNamePattern]">
    </div>
    <button class="btn" type="success" @click="submit">確認</button>
  </div>
</template>
<script lang='ts'>
import { Component, Vue, Prop, Mixins } from 'vue-property-decorator';
import { max, min, required, name, pattern} from 'rules';
import { yourMixin } from 'yourMixin.ts';

@Component({})
export default class Auth Mixins(youMixin) {
  private userName: string = '';
  private inputNameMax = max('請不要超過20個字符');
  private inputNameMin = min('請不要小於3個字符');
  private inputNameRequired = required('請輸入用戶名');
  private inputNamePattern  = pattern('請輸入符合要求的用戶名', /^[a-zA-Z0-9_-]{4,16}$/);
  private submit() {
    const validRes = this.GValidate(); // 全局校驗
    const userNameValidRes = this.GValidate(this.$refs.userName); // 單獨校驗某個表單
    if (validRes && userNameValidRes) {
      alert('經過校驗');
    } else {
      alert('校驗失敗');
    }
  }
}
</script>
複製代碼

咱們能夠看到這種方式提供了一個能夠訪問當前組件的公共方法。當咱們想校驗的時候,只須要引入並使用這個方法便可。經過這種方式的改造,將表單插件內部邏輯和校驗過程獨立開了。校驗函數只返回校驗的結果,咱們能夠拿到這個校驗結果接着寫任何本身想要的邏輯,使用起來更方便。api

參考文章

vue插件前端工程師

vue混入mixindom

重構:從 0.1 構建一個 Vue 表單驗證插件

va.js——Vue 表單驗證插件的寫做過程


做者簡介: 宮晨光,人和將來大數據前端工程師。

相關文章
相關標籤/搜索