使用vue中的混入mixin优化表单验证插件

栏目: 编程语言 · 发布时间: 5年前

内容简介:之前写了一篇介绍在vue项目中,如何使用自定义指令开发表单验证插件的博客。时隔一个多月的时间,我来更新上一篇文章中所遗留的问题了。这段时间开发的时候使用到了这个表单校验插件,用起来比较麻烦就不说了,还有较严重的缺陷。自己最终还是抽空把这个插件进行了一些优化,虽然优化的方式和当初自己定下的方向不怎么相同,但是就使用体验上来说还是提高了很多。在上面的文章中提及了一些表单插件的问题,主要针对的是插件开发本身存在的问题。下面我总结下使用中存在的问题:一开始我的目标是按照之前计划的方向,研究如何使用事件订阅发布来实现

之前写了一篇介绍在vue项目中,如何使用自定义指令开发表单验证插件的博客。时隔一个多月的时间,我来更新上一篇文章中所遗留的问题了。这段时间开发的时候使用到了这个表单校验插件,用起来比较麻烦就不说了,还有较严重的缺陷。自己最终还是抽空把这个插件进行了一些优化,虽然优化的方式和当初自己定下的方向不怎么相同,但是就使用体验上来说还是提高了很多。

1. 实际开发中遇到的问题

在上面的文章中提及了一些表单插件的问题,主要针对的是插件开发本身存在的问题。下面我总结下使用中存在的问题:

  1. 每个使用表单校验的元素都需要添加 v-check 类名,比较麻烦。
  2. 必须在提交表单按钮上使用 v-checkSubmit 指令进行表单校验,提交函数必须命名为 submit() ,而且二者还是绑定的。
  3. 无法在一个组件里面多次使用校验函数,无法自定义校验的表单范围。(严重问题)

2. 对问题进行分析

一开始我的目标是按照之前计划的方向,研究如何使用事件订阅发布来实现表单校验,但是评估之后这种方式会对现有的代码改动较大,因为我项目已经几处用了当前的校验方法,遂放弃这个方向。

经过查阅资料和思考,我发现vue本身是没有直接处理、生成dom元素的api。所以当前的这种方法(根据校验结果添加类名 input-error ,并追加错误信息元素)虽然不优雅,但是确实最简单有效的方式了。在这个基础上针对上面列出的几个问题,我分别整理了解决的思路:

v-check

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呢

// 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的校验方法

@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 指令的部分删除了。

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>
复制代码

我们可以看到这种方式提供了一个可以访问当前组件的公共方法。当我们想校验的时候,只需要引入并使用这个方法即可。通过这种方式的改造,将表单插件内部逻辑和校验过程独立开了。校验函数只返回校验的结果,我们可以拿到这个校验结果接着写任何自己想要的逻辑,使用起来更方便。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

The Shallows

The Shallows

Nicholas Carr / W. W. Norton & Company / 2010-6-15 / USD 26.95

"Is Google making us stupid?" When Nicholas Carr posed that question, in a celebrated Atlantic Monthly cover story, he tapped into a well of anxiety about how the Internet is changing us. He also crys......一起来看看 《The Shallows》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具