我们提供安全,免费的手游软件下载!
在工作中我经常需要处理一些复杂、动态表单,但是随着需求不断迭代,我们也许会发现曾经两三百行的
.vue
文件现在不知不觉到了两千行,三千行,甚至更多...
这对于一个需要长期维护的项目,无疑是增加了很多难度。
因此,为了减小文件大小,优化表单组织的结构,我在日常的开发中实践出一种基于组件的表单拆分方法,同时还能保证所有的表单项是处于同一个
el-form
中。
这对于一个一开始就没有做好文件组织,组件化的项目,有以下几个优点:
接下来我们会通过完成一个实际表单的方式来介绍如何实践这种表单组织方式。
以
element-ui
文档中的这个
表单
为例,接下来尝试用我们的方式来实现
首先假设我们当前有一个
vue
文件
./form/myForm.vue
...
如果我们直接按照
element-ui
的表单文档来写,那么我们的
myForm.vue
文件可能就会变成这样:
-
立即创建
取消
假设我们还需要为这个表单增加审批流程,例如文档中的这个
表单
在加入新的表单项后,可能目前看着还好,但是随着表单项越来越多,这个文件会变得越来越大,越来越难以维护。所以我们尝试将这个表单项拆分为单个组件,模拟我们维护一个超大表单的场景。
我习惯在当前表单的目录下,创建一个
components
目录,然后在
components
目录下创建一个
audit
目录,并在
audit
目录下创建一个
index.vue
文件,用于存放审批流程相关的组件。如果后续有一些只有
audit/index.vue
文件中才用到的组件,我也会放在
audit
目录下。保持目录结构清晰。
因为
element-ui
在对表单进行校验时,实际上是对
model
上绑定的数据进行校验,所以为了能够对数据正确执行校验,我们需要在
auditFormItem
组件中实现
v-model
指令。
auditFormItem
组件的
propPrefix
属性用于指定表单项的前缀,便于我们在嵌入到
el-form
中时,能够正确绑定表单项的
prop
属性。
auditFormData
函数返回了当前表单项的默认数据。父组件通过执行该函数,可以对子表单执行正确的初始化。不仅如此,通过这种方式,我们将每个子表单项的数据和组件绑定在一起,避免了父组件data中出现大量表单项数据,导致难以维护的问题。每个子表单维护各自的数据,互不干扰。
接下来我们尝试将
auditFormItem
组件嵌入到
myForm.vue
文件中
经过上面的操作,我们实现了将一个表单拆分为多个子表单项,那么如何进行表单校验呢?
我们知道在
element-ui
中,要对一个表单项进行校验有两种方式:
一种是在
el-form
上绑定
rules
属性,它会通过
prop
进行索引,自动对绑定的表单项进行校验。
另一种是在
el-form-item
上绑定
rules
属性,这会对单条表单项进行校验。
出于我们拆分表单项的场景,我们选择第二种方式,在
el-form-item
上绑定
rules
属性,然后在各个子组件中维护
rules
。如果有一些通用的校验规则,我们也可以在
audit/validate.js
文件中进行维护,然后通过
import
的方式引入。
在复杂表单中,我们可能需要对多个表单项进行联动校验,例如:实时校验表单项的合法性,当
form.region
为
shanghai
时,
form.user
不能为空,当
form.region
为
beijing
时,
form.user
必须为空。
那么如何处理这种联动校验呢?
我们可以在
el-form
所在的组件中,定义一个validate方法,通过
element-ui
提供的
validateField
方法,对特定进行校验。
methods: {
validate(fields) {
this.$refs.form.validateField(fields)
}
}
然后在
audit/index.vue
文件中,我们可以通过
$emit('validate', fields)
方法,对当前表单项进行校验。
在我们拆分表单为多个子组件后,还可能会出现不同子组件之间的联动校验,例如:当子组件1中的
form.region
为
shanghai
时,子组件2中的
form.user
不能为空。
对于这个问题,其实我目前还没有想到很好的解决方案,当前是在
el-form
所在的组件中,定义额外的校验规则,然后绑定到一个空白的
el-form-item
上。
rules: {
_form_validate_: {
validator: (rule, value, callback) => {
// 联动校验逻辑
}
}
}
也可以考虑用vuex来维护需要跨组件共享的数据。
const crossCmpConfig = {
state: {
region: '',
},
mutations: {
UPDATE: (state, { key, val }) => {
state[key] = val
},
},
}
export default crossCmpConfig
基于上面的方式,很容易就能想到,我们甚至可以继续在
audit/index.vue
文件中,继续嵌入别的子组件,例如:
audit/audit-info/index.vue
, 然后通过相同的方式,继续嵌入到
audit/index.vue
文件中。
上面就是我日常开发中,处理复杂表单的一些经验总结,希望对大家有所帮助。
热门资讯