关注 前端技术专栏 ,回复“ 资源 ”免费领取全套视频教程 前言 在使用Vue写移动端开发的时候,难免会遇到需要写很多的表单,所以我在现在的项目里面集成了有赞的Vant-ui组件库,但是感觉Vant-ui对于表单组件的调用方式有点繁琐,实在不愿意去干这么一样的事情,就封装了一个基于Vant-ui的数据驱动式表单自动生成组件。 具体怎么玩,我们下面一起来看看吧~ 正文
组件现在的状态
-
目前已经集成的组件如下:
Address、Checkbox、DatePicker、Input、Radio、Select、Text、Switch、Upload
其它组件还在完善中...
-
组件的调用方式采取json配置的形式,具体参数见model数据说明
-
校验规则已经集成VeeValidate插件,也可以自定义扩展规则,更多资料: https://logaretm.github.io/vee-validate
安装
# yarnyarn add @xuanmo/v-form# npmnpm install @xuanmo/v-form -S
使用
配置vue.config.js配置组件编译(注:如果组件引入采取的后编译需要配置这一项)
module.exports = { transpileDependencies: [ '@xuanmo/v-form' ]}
Props
| 字段名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| v-model(value) | 获取组件处理完成的数据 | object | {} |
| model | 数据模型(具体类型参考后续文档) | object | {} |
| disabled | 是否禁用表单 | boolean | false |
| label-width | label宽度 | string | 20% |
| label-position | label对齐方式,可选:left/right | string | left |
| label-color | label文字颜色 | string | - |
| show-label | 是否显示label | boolean | true |
event
| 事件名 | 说明 | 回调参数 |
|---|---|---|
|
change |
数据更改时触发 |
object{value,errorMsg,isValid} |
|
event |
数据发生改变所发送的事件 |
object{event,formModel} |
组件可接受多个slot,用于替换当前行的表单组件,会为该slot传入该组件的原始数据,每个slot的name为当前行的key
注:该slot不继承所有校验规则
<v-form :model="model"> <template v-slot:text="{ data }"> <van-field v-model="data.value"></van-field> </template> <!-- 行扩展字段slot,格式{key}-extra --> <template #text-extra> extra </template></v-form>
示例
main.js中全局注册
import "@vant/touch-emulator";// 如果没有安装vant-ui可以采取这种方式引入组件import VForm from "@xuanmo/v-form/dist/v-form.umd.js";import "@xuanmo/v-form/dist/v-form.css";// 项目已经引入vant-ui推荐使用这种方式引入,后编译// import VForm from '@xuanmo/v-form'Vue.use(VForm);Vue.config.productionTip = false;new Vue({ render: h => h(App)}).$mount("#app");
页面中使用
<template> <div id="app"> <div style="margin-bottom: 30px"> <span style="vertical-align: super;">切换表单禁用状态</span> <van-switch v-model="disabled" size="20px" /> </div> <v-form ref="vform" v-model="formValue" :model="model" :disabled="disabled" label-width="100px" @change="_change" @event="_event" > <template #text1-label> 自定义label </template> <template #text1-extra> <!-- <van-field v-model="data.value"></van-field> --> extra </template> </v-form> <div style="margin: 20px 0;text-align: center;"> <van-button type="primary" @click="_submit">提交数据</van-button> </div> </div></template><script>import { Switch, Button } from 'vant'export default { name: 'App', components: { // 'van-field': Field, 'van-switch': Switch, 'van-button': Button }, data () { return { formValue: { text: 1 }, formData: {}, formError: [], isValid: false, disabled: false, model: { numberKeyboard: { value: '', rules: { label: '数字键盘', type: 'VNumberKeyboard', placeholder: '点击输入', // theme: 'custom', extraKey: '.', // closeButtonText: '完成' } }, file: { value: [{ path: 'https://www.xuanmo.xin/wp-content/uploads/2019/10/xuanmo_avatar.JPG' }], rules: { label: '文件上传', type: 'VUpload', action: 'xxx', accept: 'image/png', multiple: true, name: 'file', data: { dir: 'test' }, props: { url: 'path' } } }, switch: { value: true, rules: { label: '是否启用编辑', type: 'VSwitch' } }, text: { value: '', rules: { label: '文字', type: 'VInput', vRules: 'required|max:2', placeholder: '请输入文字', errorMsg: '请输入文字', extra: 'extra' } }, text1: { value: '文字内容', rules: { label: '文字1', type: 'VText' } }, checkbox: { value: ['a'], rules: { label: '复选框', type: 'VCheckbox', vRules: 'required', placeholder: '请输入复选框', errorMsg: '请输入复选框', direction: 'horizontal', options: [ { label: '复选框 a', value: 'a' }, { label: '复选框 b', value: 'b' }, { label: '复选框 c', value: 'c' } ] } }, radio: { value: 'b', rules: { label: '单选框', type: 'VRadio', vRules: 'required', disabled: true, placeholder: '请输入单选框', errorMsg: '请输入单选框', direction: 'horizontal', options: [ { label: '复选框 a', value: 'a' }, { label: '复选框 b', value: 'b' }, { label: '复选框 c', value: 'c' } ] } }, date: { value: Date.now(), rules: { label: '时间', type: 'VDatePicker|datetime', valueFormat: 'timestamp' } }, dateRange: { value: [Date.now(), Date.now()], rules: { label: '时间', type: 'VDatePickerRange|time', valueFormat: 'timestamp', rangeSeparator: '至' } }, number: { value: '', rules: { label: '数字', type: 'VInput|digit', vRules: 'required', placeholder: '请输入数字', errorMsg: '请输入数字' } }, address: { value: '110000,110100,110114', rules: { label: '地址选择', type: 'VAddress', vRules: 'required', placeholder: '请输入地址', errorMsg: '请输入地址' } }, textarea: { value: '', rules: { label: '文本域', type: 'VInput|textarea', vRules: 'required', placeholder: '文本域', errorMsg: '文本域' } }, select: { value: '4', rules: { label: '选择器', type: 'VSelect', placeholder: 'picker选择器', errorMsg: 'picker选择器', vRules: 'required', options: [ { text: '杭州', value: 1 }, { text: '宁波', value: 2 }, { text: '温州', value: 3 }, { text: '嘉兴', value: 4 }, { text: '湖州', value: 5 } ] } }, selectMultiple: { value: '4,2', rules: { label: '多列选择器', type: 'VSelect', placeholder: 'picker选择器', errorMsg: 'picker选择器', options: [ [ { text: '杭州', value: '1' }, { text: '宁波', value: '2' }, { text: '温州', value: '3' }, { text: '嘉兴', value: '4' }, { text: '湖州', value: '5' } ], [ { text: '杭州', value: '1' }, { text: '宁波', value: '2' }, { text: '温州', value: '3' }, { text: '嘉兴', value: '4' }, { text: '湖州', value: '5' } ] ] } } } } }, methods: { _change ({ value, errorMsg, isValid }) { this.formData = value this.formError = errorMsg this.isValid = isValid }, _event ({ type, value }) { console.log(type, value) }, _submit () { if (!this.isValid) { this.$toast(this.formError[0].errorMsg) return } this.$toast('提交成功') } }}</script><style>#app { font-size: 14px;}</style>
最终效果

说实话,自从封了这个组件就感觉对于表单的处理就只是一串数据而已,其它的基本不用管,最后直接取填完表单后的数据就可以了,减少了不少繁琐,不用到处复制粘贴,还可以自己去更好的扩展自己想要的功能。如果各位同学表示认同,可以去我的Github帮点个Star,表示支持吧~
仓库地址:
https://github.com/xuanmos/v-form 猜你爱看 手写一个符合Promise A+规范的Promise实现 一文搞懂Linux CentOS7中关于MongoDB的认证和授权设置 只需5分钟,让你了解未来可能推翻Node的新轮子 Deno 1.0微 博:前端吴佳
QQ群:856363266

长按识别二维码
关注 「前端技术专栏」加星标
每天给您推送最新原创技术文章
好看,帮点击 在看❤️