内容简介:表单验证存在于每一个后台系统中,它承载了许多的逻辑以及状态。但是,过于某些的场景,会导致代码臃肿,如何更好地梳理它,来解决开发的痛点。上篇文章介绍了,如何函数式调用表单组件从而减少维护其状态的方法实例:
表单验证存在于每一个后台系统中,它承载了许多的逻辑以及状态。但是,过于某些的场景,会导致代码臃肿,如何更好地梳理它,来解决开发的痛点。
1. 前言
上篇文章介绍了,如何函数式调用表单组件从而减少维护其状态的方法 基于Vue构造器创建Form组件的通用解决方案 。现在来介绍下如何处理表单验证问题,现有的Vue表单验证插件有 vuelidate
、 vee-validate
等,但是如果场景简单的话,没有引入插件的必要,但是场景复杂的话,验证规则又要定制化的时候,应用起来没那么顺手。所以,如何调教出一个听话的Vue表单验证插件,是十分有必要的。
2. 实例以及使用规则
实例代码: GitHub - FatGe/fat-validator: fat-validator-demo
源码: GitHub - FatGe/fat-validator: fat-validator
代码中,有
<template> <input placeholder="请输入" :class="['native-input', { 'error': !errors.get('nativeInput').success }]" v-model="form.nativeInput" v-validate:nativeInput.blur="validates.nativeInput" @focus="errors.reset('nativeInput')" /> <span class="u-info">{{ errors.get('nativeInput').warn }}</span> </template> <script> // mixin 验证结果validateResult import { validateResult } from 'fat-validator' export default { mixins: [ validateResult], data () { return { form: { nativeInput: '' }, validates: { nativeInput: [ { // 将this指针bind在当前组件内,省去传值 need: () => !!this.form.nativeInput, warn: '不能为空' } ] } } } } </script> 复制代码
上述代码中存在一下几点:
-
组件的
data
中维护表单的数据form
以及待验证的规则validates
,通过() => {}
,将this
指针绑定在当前组件内,省去传值; -
v-validate:nativeInput.blur
当前input
需要校验,校验结果的key为nativeInput
,blur
代表失焦校验; -
校验规则以及警告信息则维护在组件的
data
的validates
中; -
校验结果为
errors.get('nativeInput')
,其包含{ success: true, warn }
。
3. 原理
从实例中的 v-validate:nativeInput.blur
可以看出,选用了自定义指令作为连接被校验组件和校验规则之间的桥梁,主要是它两个特点:
- 钩子函数:Vue自定义指令,存在着
bind
、inserted
、update
等钩子函数,其中bind
、unbind
与元素的display息息相关,这样满足了表单挂载、注销的语义,且只触发一次; - 构造函数提供了大量的参数,可以方便与组件通信,如
el
、bind
等; 该自定义指令的注册如下。
Vue.directive('validate', { bind (element, binding, vnode) { // 传给参数arg => 作为校验结果中的key // 指令绑定值value => 作为校验规则 // 修饰符modifiers => 作为出发校验的event类型 const { arg: name, modifiers, value: rules } = binding const method = Object.keys(modifiers)[0] }, unbind (element, binding) { // 注册 const { arg: name, modifiers } = binding const method = Object.keys(modifiers)[0] } }) 复制代码
上述code解释了:
- 通过
this
指针将Form组件中data
传递给验证规则need function
; - 以及如何将rules传入指令中。
接下来介绍如何处理这些规则。为了减少代码之间的耦合,构建一个中间件作为了规则处理的处理中心,整体结构就变为下图
从组件到规则处理中心之间的通信如下
export default function (Vue) { Vue.directive('validate', { bind (element, binding, vnode) { //... pre code // 获取当前组件的context context = vnode.context // 将eventHandler$$1绑定在当前Form的context // 防止动态切换时无法与组件通信 if (eventHandler$$1) { eventHandler$$1.bind(context) } else { eventHandler$$1 = new eventHandler(context) } // 如果method存在的话,当event出发时的处理函数 const handler = function () { eventHandler$$1.broadcast(name) } // 在hanler中订阅一个规则处理对象 eventHandler$$1.subscribe({ name, method, rules, element, handler }) method && on(element, method, handler) }, unbind (element, binding) { //... pre code // 当Form注销时,垃圾处理 const handler = eventHandler$$1.removeSubscribe(name) method && off(element, method, handler) } }) } 复制代码
当完成组件上 v-validate
的解析时,就会在处理中心中订阅一个校验对象。处理中心的定义如下
export default class eventHandler { // 构造函数 constructor (context) { this.context = context this.subscribers = {} } // 动态切换 bind (context) { this.context = context } // 订阅,将其维护在eventHandler的subscribers内 subscribe (options) { const { name } = options this.subscribers[name] = Object.assign({}, options) } // 当校验事件触发时,进行校验 broadcast (name) { const { context, subscribers } = this const { rules } = subscribers[name] // 校验结果 const error = findFailRule(rules) return error.success } } 复制代码
需要校验时就会触发,一般的触发条件可以归类为以下两类:
- input event:blur、change、input等;
- 当点击Form的确认button时,或组件的指定event触发时。 会broadcast,通过findFailRule来获得验证失败的结果。
findFailRule = (value = {}, rules) => { let failRule = null if (Array.isArray(rules)) { failRule = rules.find(item => { return !item.need(value) }) } return { warn: failRule ? failRule.warn : '', success: !failRule } } 复制代码
在组件的data中,
validates: { nativeInput: [ { need: () => !!this.form.nativeInput, warn: '不能为空' } ] } 复制代码
将验证规则定义为Array,这样方便遍历,同时也会只获取第一个报错信息。 在broadcast中获取了验证结果之后,就需要将其传递给组件。
const validateResult = { data () { return { errors: { get (param) { return this[param] ? this[param] : { warn: '', success: true } } } } } } 复制代码
维护一个 validateResult
对象,通过 mixins
注入到Form组件内,在之前,我们将 eventHandler
绑定在当前 context
内,这样可以获取到注入的 errors
状态,当校验完成时
broadcast (name) { const { context, subscribers } = this const { element, rules } = subscribers[name] const error = findFailRule(rules) // 脏更新 context.errors[name] = error context.$forceUpdate() return error.success } 复制代码
以上是一个简单的Vue表单验证插件的雏形,为了方便开发业务,还需它具备以下API:
validate validateAll reset resetAll
为了方便引入,利用 Vue.use()
将上述自定义指令封装程Vue的插件。
以上所述就是小编给大家介绍的《实现Vue表单验证插件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 使用vue中的混入mixin优化表单验证插件
- 【vue插件篇】vue-form-check 表单验证
- 使用vue自定义指令开发一个表单验证插件validate.js
- 表单 – 避免Symfony强制显示表单字段
- 细说 Angular 2+ 的表单(二):响应式表单
- 8款最新CSS3表单 环形表单很酷
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。