mpVue 微信小程序基于vant-weapp 组件的二次封装TForm 表单组件(修改源码插槽使用)

一、前言

1、mpVue微信小程序不支持动态组件(<component> )

2、mpVue微信小程序不支持动态属性及事件穿透($attrs$listeners

3、mpVue微信小程序不支持render函数

二、最终效果

在这里插入图片描述

三、配置参数(Attributes)

1. 简介:基于 vant-weapp 组件的二次封装,着重于数据层面,HTML 一行代码

TForm 表单组件
代码示例:

<t-formref="t-form":formOpts="formOpts":listDefaultInfo="formOpts.listDefaultInfo":listTypeInfo="formOpts.listTypeInfo"/>

2. 配置参数

参数说明类型默认值
className自定义类名String-
listTypeInfo下拉选择数据源(type:'date/datetime/radio/checkbox’有效)Object{}
listDefaultInfo下拉选择默认值及弹窗字段(type:'date/datetime/radio/checkbox’有效)Object{}
formOpts表单配置项Object{}
—fieldListform 表单每项 list (输入框继承van-field)Array[]
------slotName自定义表单某一项输入框String/slot-
------eventtype非date/datetime/radio/checkbox有效String-
------typedate/datetime/radio/checkbox/text/password/textareaString-
------labelform 表单每一项 titleString-
------labelCustom自定义某一项 titleString-
------slotRightIconvan-field右侧iconObject-
----------nameicon 名称String-
----------fun点击icon事件funciton-
----------coloricon颜色String-
------slotButtonvan-field右侧按钮Object-
----------name按钮显示文字String-
----------fun点击按钮事件funciton-
----------type继承van-button typeString-
----------size继承van-button sizeString-
------valueform 表单每一项传给后台的参数(对应formData每一项)String-
------required是否显示红点Booleanfalse
------list下拉选择数据源(仅仅对 type:'date/datetime/radio/checkbox’有效)String-
------defaultValue表单下拉选择回显界面值(type:'date/datetime/radio/checkbox’有效)String-
------defaultPopup表单下拉选择弹窗字段值(type:'date/datetime/radio/checkbox’有效)String-
—formData表单提交数据(对应 fieldList 每一项的 value 值)Object-
—rules三种规则校验(required(是否必填)/min:max(最小最大)/pattern(正则校验)Object-

3. events

事件名说明返回值
handleEvent输入框触发事件fieldList event 值及/输入框–输入的值

4. Methods

事件名说明参数
validateField单个字段校验传入rules值
validate整个表单校验成功返回true-

四、源码

<template><div :class="['t_form',className]"><div v-for="(item, index) in formOpts.fieldList" :key="index"><!-- 日期年月日 --><van-cell-group v-if="item.type === 'date'"><van-cell:title="item.label":required="item.required"input-align="right"is-link:value-class="listDefaultInfo[item.defaultValue]?'van-cell_date_select':'van-cell_date'":arrow-direction="listDefaultInfo[item.defaultPopup]?'down':''":value="listDefaultInfo[item.defaultValue] || item.placeholder"@click="listDefaultInfo[item.defaultPopup] = true"/><van-popup :show="listDefaultInfo[item.defaultPopup]" position="bottom" round><div class="popup_wrap"><van-datetime-picker:type="item.type||'date'":value="formOpts.formData[item.value]"@cancel="listDefaultInfo[item.defaultPopup] = false"@confirm="(e) => {listDefaultInfo[item.defaultValue] = dayjs(e.mp.detail).format('YYYY-MM-DD'),formOpts.formData[item.value] = dayjs(e.mp.detail).format('YYYY-MM-DD'),listDefaultInfo[item.defaultPopup] = false}"/></div></van-popup></van-cell-group><!-- 日期年月日时分秒 --><van-cell-group v-else-if="item.type === 'datetime'"><van-cell:title="item.label"input-align="right":required="item.required"is-link:value="listDefaultInfo[item.defaultValue] || item.placeholder":arrow-direction="listDefaultInfo[item.defaultPopup]?'down':''":value-class="listDefaultInfo[item.defaultValue]?'van-cell_date_select':'van-cell_date'"@click="listDefaultInfo[item.defaultPopup] = true"/><van-popup :show="listDefaultInfo[item.defaultPopup]" position="bottom" round><div class="popup_wrap"><van-datetime-picker:type="item.type||'datetime'":value="formOpts.formData[item.value]"@cancel="listDefaultInfo[item.defaultPopup] = false"@confirm="(e) => {listDefaultInfo[item.defaultValue] = dayjs(e.mp.detail).format('YYYY-MM-DD HH:mm:ss'),formOpts.formData[item.value] = dayjs(e.mp.detail).format('YYYY-MM-DD HH:mm:ss'),listDefaultInfo[item.defaultPopup] = false}"/></div></van-popup></van-cell-group><!-- 下拉单选框 --><van-cell-group v-else-if="item.type === 'radio'"><van-cell:title="item.label"input-align="right":required="item.required"is-link:value="listDefaultInfo[item.defaultValue] || item.placeholder":arrow-direction="listDefaultInfo[item.defaultPopup]?'down':''":value-class="listDefaultInfo[item.defaultValue]?'van-cell_date_select':'van-cell_date'"@click="listDefaultInfo[item.defaultPopup] = true"/><van-popup :show="listDefaultInfo[item.defaultPopup]" position="bottom" round><van-pickershow-toolbar:title="item.label":columns="listTypeInfo[item.list]"@cancel="listDefaultInfo[item.defaultPopup] = false"@confirm="(e) => {listDefaultInfo[item.defaultValue] = e.mp.detail.value,formOpts.formData[item.value] = e.mp.detail.value,listDefaultInfo[item.defaultPopup] = false}"/></van-popup></van-cell-group><!-- 下拉复选框 --><van-cell-group v-else-if="item.type === 'checkbox'"><van-cell:title="item.label"input-align="right":required="item.required"is-link:value="listDefaultInfo[item.defaultValue].length>0?listDefaultInfo[item.defaultValue]:listDefaultInfo[item.defaultValue].length || item.placeholder":arrow-direction="listDefaultInfo[item.defaultPopup]?'down':''":value-class="listDefaultInfo[item.defaultValue].length?'van-cell_date_select':'van-cell_date'"@click="listDefaultInfo[item.defaultPopup] = true"/><van-popup:show="listDefaultInfo[item.defaultPopup]"custom-class="t_checkbox_picker"position="bottom"round><div class="t_checkbox_picker__toolbar"><divclass="t_checkbox_picker__cancel"@click="listDefaultInfo[item.defaultPopup] = false">取消</div><div class="t_checkbox_picker__title t-oneline-overflow-hidden">{{item.label}}</div><divclass="t_checkbox_picker__confirm"@click="() => {formOpts.formData[item.value] = listDefaultInfo[item.defaultValue],listDefaultInfo[item.defaultPopup] = false}">确认</div></div><van-checkbox-group:value="listDefaultInfo[item.defaultValue]"@change="(event)=>listDefaultInfo[item.defaultValue] = event.mp.detail"><divv-for="(value,key) in listTypeInfo[item.list]":key="key"class="t_checkbox_content"><van-checkboxcustom-class="t_checkbox":name="value[arrLabel || 'label']":disabled="value.disabled||false"shape="square">{{value[arrLabel || 'label']}}</van-checkbox></div></van-checkbox-group></van-popup></van-cell-group><!-- 自定义插槽 --><template v-else-if="item.slotName"><slot :name="item.slotName"></slot></template><!-- 输入框 --><van-cell-group v-else><van-field:name="item.value"v-model="formOpts.formData[item.value]":placeholder="item.placeholder||''":label="item.label":type="item.type":disabled="item.disabled":readonly="item.readonly":required="item.required":title-width="item.titleWidth||'6.2em'":maxlength="item.maxlength||-1":cursor="item.cursor||0":show-word-limit="item.showWordLimit":is-link="item.isLink":input-align="item.inputAlign||'right'":autosize="item.autosize||item.type==='textarea'":left-icon="item.leftIcon||''":right-icon="item.rightIcon||''"clearable@change="e => formOpts.formData[item.value] = e.mp.detail"@click="() =>$emit('handleEvent',item.event,formOpts.formData[item.value])"><divv-if="!item.label":class="item.labelNameClass":style="item.labelNameStyle"slot="label">{{item.labelCustom}}</div><van-iconv-if="item.slotLeftIcon":class="item.slotLeftIcon.class":color="item.slotLeftIcon.color||'inherit'"@click="item.slotLeftIcon.fun":name="item.slotLeftIcon.name"slot="left-icon"/><van-iconv-if="item.slotRightIcon":class="item.slotRightIcon.class":color="item.slotRightIcon.color||'inherit'":name="item.slotRightIcon.name"@click="item.slotRightIcon.fun"slot="right-icon"/><van-buttonv-if="item.slotButton&&item.slotButton.name":class="item.slotButton.class":style="item.slotButton.style":size="item.slotButton.size":type="item.slotButton.type"@click="item.slotButton.fun"slot="button">{{item.slotButton.name}}</van-button></van-field></van-cell-group></div></div>
</template>
<script>
import dayjs from 'dayjs'
export default {name: 'TMobileForm',components: {},props: {/** 表单配置项说明* formData object 表单提交数据* rules object 验证规则* fieldList Array 表单渲染数据*/formOpts: {type: Object,default: () => ({})},// 下拉选项数据listTypeInfo: {type: Object,default: () => ({})},// 下拉选择默认值listDefaultInfo: {type: Object,default: () => ({})},className: String},computed: {dayjs() {return dayjs}},data() {return {...this.listDefaultInfo}},methods: {// 单个字段校验validateField(key) {let value = this.formOpts.formData[key]if (this.formOpts.rules[key] && this.formOpts.rules[key].length) {for (let i = 0; i < this.formOpts.rules[key].length; i++) {let rule = this.formOpts.rules[key][i]if (rule.required) {// 必填校验if (!value) {return {valid: false,msg: rule.message}}} else if (rule.max || rule.min) {// 最大最小长度校验if (value && (value.length > rule.max || value.length < rule.min)) {return {valid: false,msg: rule.message}}} else if (rule.pattern && value) {// 正则校验let reg = new RegExp(rule.pattern)if (!reg.test(value)) {return {valid: false,msg: rule.message}}}}}return {valid: true}},// 全部校验validate() {let res = []Object.keys(this.formOpts.rules).forEach(key => {res.push(this.validateField(key))})for (let i = 0; i < res.length; i++) {if (!res[i].valid) {wx.showToast({title: res[i].msg,icon: 'none'})return false}}return true}}
}
</script>
<style lang="css">
.t_form .van-cell_date {color: var(--cell-value-color, #c8c9cc);
}
.t_form .van-cell_date_select {color: var(--cell-value-color, #000);
}
.t_form .t_checkbox_picker {min-height: 260px;padding: 10px 15px;
}
.t_form .t_checkbox_picker .t_checkbox_picker__toolbar {display: flex;height: var(--picker-toolbar-height, 44px);justify-content: space-between;line-height: var(--picker-toolbar-height, 44px);
}
.t_form.t_checkbox_picker.t_checkbox_picker__toolbar.t_checkbox_picker__cancel {color: var(--picker-cancel-action-color, #969799);font-size: var(--picker-action-font-size, 14px);padding: var(--picker-action-padding, 0 16px);
}.t_form.t_checkbox_picker.t_checkbox_picker__toolbar.t_checkbox_picker__confirm {font-size: var(--picker-action-font-size, 14px);padding: var(--picker-action-padding, 0 16px);color: var(--picker-confirm-action-color, #576b95);
}
.t_form.t_checkbox_picker.t_checkbox_picker__toolbar.t_checkbox_picker__title {font-size: var(--picker-option-font-size, 16px);font-weight: var(--font-weight-bold, 500);max-width: 50%;text-align: center;
}
.t_form .t_checkbox_picker ._van-checkbox-group .t_checkbox_content {margin: 10px;
}
</style>

五、页面使用

<template><div class="demo_form"><t-header title="表单组件示例" /><t-mobile-formref="t-form":formOpts="formOpts":listDefaultInfo="formOpts.listDefaultInfo":listTypeInfo="formOpts.listTypeInfo"></t-mobile-form><van-button block type="primary" @click="formCom">表单组件</van-button></div>
</template>
<script>
export default {name: 'DemoForm',data() {return {formOpts: {formData: {account: '', // *用户账号password: '', // *用户密码name: '', // *用户昵称email: '', // 邮箱desc: '', // 描述sex: '', // *性别: 0:男 1:女status: '', // *状态: 停用,启用',hobby: '', // *爱好:多选creatDate: '', // 出生日期date: '', // 出生日期---时分秒phone: '' // 手机号码},// 下拉选择默认值listDefaultInfo: {statusDefault: '',statusPopup: false,sexDefault: '',sexPopup: false,showDatePopup: false, // 日期弹窗showDatetimePopup: false, // 日期弹窗(含时分秒)dateDefault: '', // 默认日期-- 年月日datetimeDefault: '', // 默认日期--含时分秒hobbyPopup: false, // 爱好弹窗hobbyDefault: [] // 爱好},fieldList: [{ label: '账号', value: 'account', type: 'text', placeholder: '请输入账号', required: true },{ label: '', value: 'password', type: 'password', placeholder: '请输入密码', required: true, labelCustom: '自定义label', labelNameStyle: 'color:red', slotRightIcon: { name: 'location-o', fun: this.clickIcon } },{ label: '昵称', value: 'name', type: 'text', placeholder: '请输入昵称', required: true, slotButton: { name: '发送验证码', size: 'small', type: 'primary', fun: this.test } },{ label: '邮箱', value: 'email', type: 'text', placeholder: '请输入邮箱', required: true },{ label: '出生日期', value: 'creatDate', type: 'date', placeholder: '请选择出生日期', defaultValue: 'dateDefault', defaultPopup: 'showDatePopup' },{ label: '日期时分秒', value: 'date', type: 'datetime', placeholder: '请选择日期时分秒', defaultValue: 'datetimeDefault', defaultPopup: 'showDatetimePopup' },{ label: '性别', value: 'sex', type: 'radio', list: 'sexList', placeholder: '请选择性别', defaultValue: 'sexDefault', defaultPopup: 'sexPopup' },{ label: '爱好', value: 'hobby', type: 'checkbox', list: 'hobbyList', placeholder: '请选择爱好(多选)', required: true, defaultValue: 'hobbyDefault', defaultPopup: 'hobbyPopup' },{ label: '状态', value: 'status', type: 'radio', list: 'statusList', placeholder: '请选择状态', defaultValue: 'statusDefault', defaultPopup: 'statusPopup' },{ label: '手机号码', value: 'phone', type: 'text', maxlength: 11, placeholder: '请输入手机号码', required: true },{ label: '描述', value: 'desc', type: 'textarea', placeholder: '请输入描述', autosize: { maxHeight: 80, minHeight: 50 } }],rules: {account: [{ required: true, message: '请输入账号' },{ min: 2, max: 4, message: '账号只能大于2个字符小于4个字符' }],password: [{ required: true, message: '请输入密码' }],name: [{ required: true, message: '请输入昵称' }],email: [{ required: true, message: '请输入邮箱' },{ pattern: /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/, message: '请输入正确的邮箱' }],hobby: [{ required: true, message: '请至少选择一个爱好' }],phone: [{ required: true, message: '请输入手机号码' },{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码' }]},// 相关列表listTypeInfo: {hobbyList: [{ label: '吉他', value: '0' },{ label: '看书', value: '1' },{ label: '美剧', value: '2' },{ label: '旅游', value: '3' },{ label: '音乐', value: '4' }],sexList: ['女', '男'],statusList: ['启用', '停用']}}}},methods: {// TForm表单提交formCom() {console.log('form组件点击提交--数据', this.formOpts.formData)let res = this.$refs['t-form'].validate()console.log('规则校验是否全部通过', res)if (!res) returnconsole.log('全部校验通过--最终数据', this.formOpts.formData)},test(val) {console.log('测试点击右侧按钮---', val)},clickIcon(val) {console.log('点击图标', val)}}
}
</script>
<style lang="scss">
.demo_form {width: 100%;
}
</style>

六、仓库地址

gitHub地址

码云地址

七、相关文章

Vue3 + Vite + Ts开源后台管理系统模板


基于ElementUi或AntdUI再次封装基础组件文档


基于Element-plus再次封装基础组件文档(vue3+ts)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/26473.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WEB:lottery

背景知识 dirsearch扫描 题目 原题目应该使用dirsearch扫描发现git泄露然后使用Githack复原的但是攻防世界这边直接把源码给了我们 下载附件可得到 打开文件后进行代码审计 function buy($req){require_registered();require_min_money(2);$money $_SESSION[money];$numbers…

VBA命令及语法列表之字典Dictionaries相关

【分享成果&#xff0c;随喜正能量】真正的修佛之人。首先&#xff0c;得明白自己的来处和归宿&#xff0c;懂得敬畏自己的生命和他人的生命&#xff0c;尽其所能释放善意。学会悲天悯人&#xff0c;渡人的同时渡己&#xff0c;始终走在止于至善的路上。真正的慈悲为怀&#xf…

【unity细节】为什么发射炮弹实例化出来了却无法移动

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏&#xff1a;unity细节和bug ⭐为什么发射炮弹实例化出来了却无法移动⭐ 文章目录 ⭐为什么发射炮弹实例化出来…

Pytest+Jenkins+Allure的接口自动化测试

目录 生成Allure 两种形式 一 项目内直接生成不依赖Jenkins 1.先安装好allure 将allure\bin配置到环境变量中 cmd 命令行输入&#xff1a;allure 校验是否安装成功 2. 将json文件生成html文件 执行 allure generate report/ -o report/html其中的report/ 为生成的json路径&a…

带你了解储能行业PCB的设计与应用

高速先生成员---黄刚 高速先生有接触过储能相关的互连设计吗&#xff1f; 突然被粉丝一问&#xff0c;高速先生在大脑里面不停的搜索&#xff0c;的确储能方面的PCB设计板子很少有进来高速先生团队这边的&#xff0c;难道我们真的没怎么做过&#xff1f;这个问题高速先生先不回…

Vue+Ts+Echart使用以及后台接口对接逻辑【实战】

官网传送门 一.echarts介绍 是一个js插件 性能好可流畅远行PC和移动设备 兼容主流浏览器 提供很多图标,用户且可自行修改。 2.使用npm安装 npm install echarts二.echarts基本使用、自定义图例、选择7天日期查询图表数据内容 获取本地时间以及当前时间前几天后几天 /*** 获…

PWM呼吸灯设计

呼吸灯&#xff1a; 呼吸灯是一种特殊的灯光效果&#xff0c;它可以模拟呼吸的效果&#xff0c;即灯光逐渐由暗变亮再由亮变暗&#xff0c;循环往复。这种效果给人一种柔和、舒缓的感觉&#xff0c;常被应用在装饰、照明和显示等领域。 PWM呼吸灯设计&#xff1a; 在数字电路设…

数据结构 ~ 树

什么是树 - tree 一种分层数据的抽象模型&#xff1b; 如&#xff1a;DOM、级联选择、树形控件&#xff0c;js 中没有树 可以用 Object 构建树&#xff1a; const tree {val: a,children: [{val: a-1,children: [{val: a-1-1,children: []}]},{val: a-2,children: [{val: a…

CMS垃圾收集器三色标记-JVM(十二)

上篇文章说了CMS垃圾收集器是赋值清除&#xff0c;所以他不可以碎片整理&#xff0c;于是jvm支持两个参数&#xff0c;几次fullGC之后碎片整理压缩空间。Cms他会抢占cpu资源&#xff0c;因为是并行运行&#xff0c;所以会有浮动垃圾。还有执行不确定性&#xff0c;垃圾收集完&a…

VsCode添加Vue模版代码片段

文章目录 VsCode添加Vue模版代码片段1. 复制一段已有要制作模板的Vue代码&#xff0c;比如&#xff1a;2. 粘贴到下方链接的工具网站&#xff0c;可自动生成模板代码的片段3. VsCode中设置代码片段3-1 打开菜单&#xff1a;首选项-用户片段3-2 出现如下的搜索栏&#xff0c;搜索…

Ubuntu下搭建Redis主从集群

目录 准备实例和配置 开启主从关系 测试配置 搭建的主从集群结构&#xff0c;只有主服务器与客户端进行写操作&#xff0c;通过主从同步数据&#xff0c;从服务器向客户端提供读操作 共包含三个节点&#xff0c;一个主节点&#xff0c;两个从节点。 这里我们会在同一台虚拟机…

2023最新软件测试面试题(带答案)

1. 请自我介绍一下(需简单清楚的表述自已的基本情况&#xff0c;在这过程中要展现出自信&#xff0c;对工作有激情&#xff0c;上进&#xff0c;好学) 面试官您好&#xff0c;我叫###&#xff0c;今年26岁&#xff0c;来自江西九江&#xff0c;就读专业是电子商务&#xff0c;毕…