实现Vue表单验证插件

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

内容简介:表单验证存在于每一个后台系统中,它承载了许多的逻辑以及状态。但是,过于某些的场景,会导致代码臃肿,如何更好地梳理它,来解决开发的痛点。上篇文章介绍了,如何函数式调用表单组件从而减少维护其状态的方法实例:

表单验证存在于每一个后台系统中,它承载了许多的逻辑以及状态。但是,过于某些的场景,会导致代码臃肿,如何更好地梳理它,来解决开发的痛点。

1. 前言

上篇文章介绍了,如何函数式调用表单组件从而减少维护其状态的方法 基于Vue构造器创建Form组件的通用解决方案 。现在来介绍下如何处理表单验证问题,现有的Vue表单验证插件有 vuelidatevee-validate 等,但是如果场景简单的话,没有引入插件的必要,但是场景复杂的话,验证规则又要定制化的时候,应用起来没那么顺手。所以,如何调教出一个听话的Vue表单验证插件,是十分有必要的。

2. 实例以及使用规则

实例: fatge.xyz/blog/juejin…

实例代码: 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为 nativeInputblur 代表失焦校验;

  • 校验规则以及警告信息则维护在组件的 datavalidates 中;

  • 校验结果为 errors.get('nativeInput') ,其包含 { success: true, warn }

3. 原理

从实例中的 v-validate:nativeInput.blur 可以看出,选用了自定义指令作为连接被校验组件和校验规则之间的桥梁,主要是它两个特点:

  • 钩子函数:Vue自定义指令,存在着 bindinsertedupdate 等钩子函数,其中 bindunbind 与元素的display息息相关,这样满足了表单挂载、注销的语义,且只触发一次;
  • 构造函数提供了大量的参数,可以方便与组件通信,如 elbind 等; 该自定义指令的注册如下。
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传入指令中。

接下来介绍如何处理这些规则。为了减少代码之间的耦合,构建一个中间件作为了规则处理的处理中心,整体结构就变为下图

实现Vue表单验证插件

从组件到规则处理中心之间的通信如下

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表单验证插件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Remote

Remote

Jason Fried、David Heinemeier Hansson / Crown Business / 2013-10-29 / CAD 26.95

The “work from home” phenomenon is thoroughly explored in this illuminating new book from bestselling 37signals founders Fried and Hansson, who point to the surging trend of employees working from hom......一起来看看 《Remote》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

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

RGB CMYK 互转工具