内容简介:表单验证存在于每一个后台系统中,它承载了许多的逻辑以及状态。但是,过于某些的场景,会导致代码臃肿,如何更好地梳理它,来解决开发的痛点。上篇文章介绍了,如何函数式调用表单组件从而减少维护其状态的方法实例:
表单验证存在于每一个后台系统中,它承载了许多的逻辑以及状态。但是,过于某些的场景,会导致代码臃肿,如何更好地梳理它,来解决开发的痛点。
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表单 环形表单很酷
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ruby on Rails实践之路
沃哈 / 科学 / 2010-5 / 48.00元
《Ruby on Rails实践之路:写给PHP和Java开发者的书》内容简介:Ruby on Rails是基于MVC模式的Web框架,用于开发基于数据库的Web应用。Ruby on Rails中内含了所需的Web服务器WEBrick。该框架配置的数据库除了缺省的MySQL外,还可以是Oracle、SQL Server等其他数据库。《Ruby on Rails实践之路:写给PHP和Java开发者的......一起来看看 《Ruby on Rails实践之路》 这本书的介绍吧!