以前做Vue项目,经常需要用到表单验证,当时为了项目的速度,为了更好的交互和上线之后更稳定的性能,一直使用的都是
VeeValidate
确实很好用很强大,但是复杂的英文API的确也在开发中给我带了一定的困难,再加上项目上的需求或多或少和插件有一点点的差别,去看源码修改插件这种事情对我这个菜鸟压力太大~~;一直痛并快乐着。
在闲鱼时间,一直希望可以系统学习一下如何封装一个form表单插件,一方面解决工作上面的痛点,一方面可以牢固所学知识。
??????????????????????????????????????????????????????????
下面的动图就是我最近学习写出来的效果,功能简单,但也因此,容易应对不通项目需求更快速的做出适当定制~
form表单组件属于基础组件(不包含任何业务逻辑 只包含某种独立功能的组件,比如模态框、日历插件也是基础组件,这种组件适用于大多数项目,通过高度抽象的API 和可定制化选项匹配大多数项目)
所以说,我们不能在form表单组件里面出现业务逻辑,它要适用于绝大多数的需要表单校验的地方,在这个表单组件里,我们使用 异步表单验证插件 async-validator。很多大型的UI框架都是使用这个插件,使用比较简单,大家可以直接去GitHub上面查看使用文档。
封装一个基础组件,一定要记住一个词 单一职责,就是一个组件模块做一件事,如果功能不同职责不一一定要再次拆开,这样可以减少代码耦合,增加组件的可复用性,逻辑更加清晰。
下面我们进入正题,我们将组件整个form表单组件分为三个部分:
简单分析完了我们即将详细讲解的几个组件,接下来我们提前分析几个特殊的功能函数,在一般写Vue 项目中我们很少用上的,但是在基础组件中,非常实用的几个工具函数。
1、 首先我们说的第一个方法是 dispatch,作用是向上指定组件暴露事件 以供监听,不限层级,直到找到为止,代码如下:
export default {
methods: {
dispatch (componentName, eventName, params) {
let parent = this.$parent || this.$root
let name = parent.$options.name
while (parent && (name !== componentName)) {
parent = parent.$parent
if (parent) {
name = parent.$options.name
}
}
parent.$emit(eventName, params)
}
}
方法接受三个参数:
2、 第二个方法是 capture,作用是向下指定组件暴露事件 以供监听,不限层级,直到找到为止,代码如下:
function loops (childrens, componentName, eventName, params) {
for (let child of childrens) {
let name = child.$options.name
if (name && name !== componentName) {
loops(child.$children, componentName, eventName, params)
} else {
child.$emit(eventName, params)
}
}
export default {
methods: {
capture (componentName, eventName, params) {
let childrens = this.$children
loops(childrens, componentName, eventName, params)
}
}
方法接受三个参数:
之所以用到这两个方法,是因为我们的form的三个基础组件之间并不一定是紧密相连的父子组件关系,用户还可能在其中嵌套其他组件,在这种情况下我们不能限制用户的组件嵌套方式。
3、另外我们还要用到
// 向上寻找指定name的组件
function findComponentUpward (context, componentName) {
let parent = context.$parent
if (!parent) {
return
}
let name = parent.$options.name
if (name === componentName) {
return parent
} else {
return findComponentUpward(parent, componentName)
}
}
export { findComponentUpward }
// 向下寻找指定name的所有组件
function findComponentsDownward (context, componentName) {
return context.$children.reduce((components, child) => {
if (child.$options.name === componentName) components.push(child)
const foundChilds = findComponentsDownward(child, componentName)
return components.concat(foundChilds)
}, [])
}
export { findComponentsDownward }
源码地址: https://github.com/wangyangsea/wy-validate
Vue.js 组件精讲