When we are doing backend management systems, we often encounter very complex forms:
- There are too many form items
- Display different form items under various form types
- Certain form items turn off validation under certain conditions
- Each form item will also have other custom logic, such as input boxes that can insert template variables, display the number of input characters, upload and display images, and rich text . . .
- In this complicated situation, complete the verification and submission of the form
- You can view specific examples: Many trivial functions are omitted in the example, and only the overall complex form framework is retained to demonstrate the solution.
vue
fileAll form item display and hiding, validation, data acquisition, submission, customization and other logic are put together
- According to the form type, use
v-if/v-show
to handle the display and hiding of form items.- In
elementui
custom validation, determine whether the form item is validated based on the form type- According to the form type, obtain different data and submit it to different interfaces
- All other custom logic
vue
file can easily contain 2000
linesIn fact, it is easy to think of separating multiple subforms of corresponding types according to different form types . But I still encountered many problems in practice: parent-child form verification, obtaining overall submitted data , etc., and summarized a set of solutions:
All child components need to contain two methods validate
and getData
for the parent component to call.
validate
method Used to verify the form items of its own components and return a promise
object
vaildate ( ) {
// 返回`elementUI`表单验证的结果(为`promise`对象)
return this . $refs [ "ruleForm" ] . validate ( ) ;
} ,
getData
methodProvide data from child components
getData ( ) {
// 返回子组件的form
return this . ruleForm ;
} ,
Use the strategy pattern to store and get ref
of the subform (the method used to get the subform) and the submit function . A lot of if-else
judgments are omitted.
data: {
// type和ref名称的映射
typeRefMap : {
1 : "message" ,
2 : "mail" ,
3 : "apppush"
} ,
// type和提交函数的映射。不同类型,接口可能不同
typeSubmitMap : {
1 : data => alert ( `短信模板创建成功${ JSON . stringify ( data ) } ` ) ,
2 : data => alert ( `邮件模板创建成功${ JSON . stringify ( data ) } ` ) ,
3 : data => alert ( `push模板创建成功${ JSON . stringify ( data ) } ` )
} ,
}
submit
methodUsed for parent-child component form validation, obtaining overall data, and calling the current type submission function to submit data
Because the
validate
method ofelementUI
form verification can return apromise
result , you can use the characteristics ofpromise
to handle the verification of parent and child forms. For example, thethen
function can return anotherpromise
object, andcatch
can obtainreject
andPromise.all
of allthen
above it.
// 父表单验证通过才会验证子表单,存在先后顺序
submitForm ( ) {
const templateType = this . typeRefMap [ this . indexForm . type ] ;
this . $refs [ "indexForm" ]
. validate ( )
. then ( res => {
// 父表单验证成功后,验证子表单
return this . $refs [ templateType ] . vaildate ( ) ;
} )
. then ( res => {
// 全部验证通过
// 获取整体数据
const reqData = {
// 获取子组件数据
... this . $refs [ templateType ] . getData ( ) ,
... this . indexForm
} ;
// 获取当前表单类型的提交函数,并提交
this . typeSubmitMap [ this . indexForm . type ] ( reqData ) ;
} )
. catch ( err => {
console . log ( err ) ;
} ) ;
} ,
submitForm1 ( ) {
const templateType = this . typeRefMap [ this . indexForm . type ] ;
const validate1 = this . $refs [ "indexForm" ] . validate ( ) ;
const validate2 = this . $refs [ templateType ] . vaildate ( ) ;
// 父子表单一起验证
Promise . all ( [ validate1 , validate2 ] )
. then ( res => {
// 都通过时,发送请求
const reqData = {
... this . $refs [ templateType ] . getData ( ) ,
... this . indexForm
} ;
this . typeSubmitMap [ this . indexForm . type ] ( reqData ) ;
} )
. catch ( err => {
console . log ( err ) ;
} ) ;
} ,
Summary: I have encountered this kind of complex forms in many projects and used many solutions. Here I have summarized a relatively neat and simple solution. Of course, there are many other solutions. For example , the data submission method can be placed in each sub-component, and the public form item data is passed to the sub-component through
props
for submission . If there are other simpler solutions, you are welcome to comment or submitissue
ongithub
Off-topic: After reading the front-end architect’s own account: N’s question and answer on the growth path of a front-end engineer, it inspired me a lot. When you are confused about your technical direction and prospects, or when you complain that your project is too low, or when you complain that you are doing repetitive work every day, or when you are overwhelmed by the endless emergence of new technologies every day , you might as well take a serious look at your project .
Starting from the pain points of work processes and projects , you will make faster progress in practicing, summarizing and solving practical problems .
My feelings about writing this article: the difficulty of expressing these things
>>
the technical difficulty contained in the article itself