基于vant封装的动态表单(VFrom使用教程)

基于vant封装的动态表单(VFrom使用教程)vant ui 是属于 vue 开发移动端中用的比较多的一个组件库了 网上基于它的一些组件的二次封装也数不胜数 但是却都是零零散散 不成体系 总不能用一个就去找类似的封装吧 这样拼凑起来的也不是我们想要的 尤其 涉及众多表单业务的时候 1 场景需求 假如你遇到这样一个场景 需要做一个表单收集

大家好,我是讯享网,很高兴认识大家。

vant-ui是属于vue开发移动端中用的比较多的一个组件库了,网上基于它的一些组件的二次封装也数不胜数,但是却都是零零散散,不成体系。总不能用一个就去找类似的封装吧,这样拼凑起来的也不是我们想要的。尤其,涉及众多表单业务的时候。

1.场景需求 

假如你遇到这样一个场景,需要做一个表单收集。涉及到输入框,单选框,多选框,下拉框,时间选择等等七八个表单。基于vant-ui的情况下,去官网单个的去复制粘贴。就这样一个vue页面是不是起码就几百行了。这还不算假如是在一个tabs标签页下,每个标签页下都有七八个表单呢?

这个时候,阁下又该如何自处?组件化,那就多少个标签多少个组件。不利于维护。改起来也麻烦。写一个页面?哪起码上千行代码了。

先看下效果图,有个最直观的感受:

所以,当涉及多个表单时,我们就迫切的需要一个成体系化的二次封装表单。


讯享网

2.vform使用说明

v-form: 🎉 基于Vant-UI进行二次封装动态生成表单,也可完全自定义控件,通过 JSON 的形式配置,内部集成繁琐的校验规则,可扩展的校验

文档有详细说明。照猫画虎对于一些动手能力强的人来说那就是手拿把掐。这里我也就不多加叙述了。

 3.从无到有

        文档上说的很清楚,也不得不承认它的封装的却是很好。不多相比于大多数业务场景而言,也用不到那么复制。就一个最常见的场景来说。生成表单,收集信息 这八个字就是我们的核心思想,迫切所需要的。

闲话少叙,跟随lz的脚步,我们一起实操下:

1.引入依赖,全局注册

 man.js

// 注册封装表单:https://gitee.com/cgb-lowcode/v-form import VForm from '@xuanmo/v-form' import '@xuanmo/v-form/packages/style/index.less' Vue.use(VForm); // 设置防抖时间,默认200ms Vue.use(VForm, { debounceTime: 200 })

讯享网

tips:项目技术栈是vue+vant。记得提前引入vant。

2.模拟动态表单数据

formModel.js

讯享网const formdata = { family:[ { rules: { type: "VCell" } }, { key:'text1', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra', } }, { key:'text2', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text3', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text4', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text5', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text6', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text7', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { rules: { type: "VCell" } }, { key:'text8', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text9', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text10', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { rules: { type: "VCell" } }, { key:'text11', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text12', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text13', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text14', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text15', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } } ], health:[ { rules: { type: "VCell" } }, { key:'text1', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra', } }, { key:'text2', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text3', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text4', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, ], children:[ { rules: { type: "VCell" } }, { key:'text1', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra', } }, { key:'text2', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text3', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text4', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { rules: { type: "VCell" } }, { key:'text5', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra', } }, { key:'text6', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, ], retire:[ { rules: { type: "VCell" } }, { key:'text1', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra', } }, { key:'text2', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text3', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text4', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text5', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text6', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { rules: { type: "VCell" } }, { key:'text7', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text8', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text9', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, ], riches:[ { rules: { type: "VCell" } }, { key:'text1', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra', } }, { key:'text2', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text3', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text4', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } }, { key:'text5', value: '', rules: { label: '文本', type: 'VInput', vRules: 'required', placeholder: '请输入', errorMsg: '请输入', extra: 'extra' } } ] } export default formdata;

3.vue页面使用

<template> <div class='dataedit'> <van-nav-bar title='数据收集' left-arrow @click-left='$router.back()' ></van-nav-bar> <div class="main"> <van-tabs @disabled="onClickDisabled" @change="changeTab" v-model.number="active" sticky color="#FF6837" title-active-color="#FF6837" line-width="0.5rem"> <van-tab disabled> <template #title><img src="@/assets/menu/11.png" alt="" style="width:0.8rem;height:0.8rem;margin-top:0.2rem"></template> </van-tab> <van-tab title="表单1"> <v-form ref="vform" v-model="formValue.family" :model="model.family" :disabled="disabled" label-width="80%" :label-color="labelColor" @change="change" > </v-form> </van-tab> <van-tab title="表单2"> <v-form ref="vform" v-model="formValue.health" :model="model.health" :disabled="disabled" label-width="80%" :label-color="labelColor" @change="change" > </v-form> </van-tab> <van-tab title="表单3"> <v-form ref="vform" v-model="formValue.children" :model="model.children" :disabled="disabled" label-width="80%" :label-color="labelColor" @change="change" > </v-form> </van-tab> <van-tab title="表单4"> <v-form ref="vform" v-model="formValue.retire" :model="model.retire" :disabled="disabled" label-width="80%" :label-color="labelColor" @change="change" > </v-form> </van-tab> <van-tab title="表单5"> <v-form ref="vform" v-model="formValue.riches" :model="model.riches" :disabled="disabled" label-width="80%" :label-color="labelColor" @change="change" > </v-form> </van-tab> </van-tabs> </div> <div class="btn"> <van-button round block type="info" color="#FF6837" to="/sys/data/addinfo">保存</van-button> </div> </div> </template> <script> import formModel from "./formModel"; export default { name: 'dataedit', data () { return { active:1, model:formModel, disabled: false, // 是否禁用表单 labelColor: "inherit", // label颜色 formValue: { // 表单值 family:{}, health:{}, retire:{}, children:{}, riches:{} }, } }, mounted(){ console.log("参数:",this.$route.query.id); }, methods: { onClickDisabled(){ console.log("点击头像"); }, change({ value, errorMsg, isValid }) { console.log("表单值:",value); this.formData = value; this.formError = errorMsg; this.isValid = isValid; }, changeTab(val){ console.log("当前标签===》",val); }, } } </script> <style lang='less' scoped> ::v-deep .v-form-container .v-form-row{ min-height: 1.5rem; padding-top: 0.25rem; } .main{ ::v-deep .van-tab__pane{ height: 80vh; overflow-y: auto; padding-bottom: 1rem; } } .btn{ position: fixed; bottom: 0; left: 0; right: 0; height: 1.6rem; display: flex; justify-content: center; align-items: center; background: #ffffff; padding: 0 5%; } </style> 

4.最终效果图

 数据是实时获取的。formModel.js定义的key值就是键。type为表单类型,如VInput,VRadio,VSelect等常用表单,label就是label文本,vRules是验证规则,placeholder是原生的placeholder,errorMsg就是验证失败提示。

其他的请自行查看文档。

小讯
上一篇 2025-01-14 07:51
下一篇 2025-03-23 23:53

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/31825.html