封装公共el-form表单(记录)

1.公共表单组件 

//commonForm.vue
<script>
import {TEXT,SELECT,PASSWORD,TEXTAREA,RADIO,DATE_PICKER
} from '@/conf/uiTypes'
import { deepClone } from '@/utils'
export default {name: 'GFormCreator',props: {config: {  // title/itemstype: Object,required: true}},created() {const { items, cards, rules } = this.config;// 绑定表单验证器thisfor (let key in rules) {rules[key].forEach(r => {// 若该方法是全局方法,第二次bind会失效,因为bind只能绑定一次if (r.validator) {r.validator = r.validator.bind(this)}}) }if (cards) {cards.forEach(card => {this.reactiveFields(card.children);})} else if (items) {this.reactiveFields(items);}},data() {return {ruleForm: {}}},methods: {reactiveFields(items) {console.log(items);if (!items) return;items.forEach((row, rowIndex) => {row.forEach((item, colIndex) => {// this.ruleForm[item.key] = item.value;// Object.defineProperty 对所有key进行响应式,更改后更新// 无法检测到动态添加的key,访问、设置,set/get都无法触发响应式 if (this.ruleForm.hasOwnProperty(item.key)) {// 异常抛出,外部方法没有捕获的画,程序结束throw new Error(`行:${rowIndex + 1}_列${colIndex + 1}` + '已经存在相同的key:' + item.key + ',value:' + item.value)}this.$set(this.ruleForm, item.key, item.value);})});},renderItem(item) {const fd = this.ruleForm;const attrs = item.attrs;switch (item.type) {case TEXT:case PASSWORD:case TEXTAREA:// v-model = @input + :valuereturn <el-input attrs={attrs} v-model={fd[item.key]} type={item.type} ></el-input>case SELECT:return <el-select attrs={attrs} v-model={fd[item.key]}>{item.options.map(opt => {return <el-option value={opt.value} label={opt.label}></el-option>})}</el-select>case DATE_PICKER:return <el-date-pickerattrs={attrs}v-model={fd[item.key]}type="date"placeholder="选择日期"></el-date-picker>case RADIO:  //  {  label:'xxx' radios:[ { attrs:{},label:'xxx' }  ] }return item?.radios?.map(radio => {console.log('radio:', fd[item.key])return <el-radioattrs={radio.attrs}v-model={fd[item.key]} label={radio.label}>{radio.title}</el-radio>})default:return <h2>未匹配{item.type}</h2>}},renderColumns(columns) {return columns.map(col => {return <el-col span={col.colspan}><el-form-item label={col.label} prop={col.key}>{this.renderItem(col)}</el-form-item></el-col>})},renderRows(rows) {return rows.map(rowArr => {return <el-row>{this.renderColumns(rowArr)}</el-row>})},getData() {return deepClone(this.ruleForm)},passData() {// submitthis.$emit('submit', deepClone(this.ruleForm));},// 外部验证// 内部验证返回数据doSubmit() {this.$refs.form.validate(valid => {if (valid) {return this.$emit('submit', deepClone(this.ruleForm));} else {console.log('验证失败');return false;}})},valid(callback) {this.$refs.form.validate(valid => {if (valid) {return callback(deepClone(this.ruleForm))} else {callback(false);console.log('验证失败');return false;}});},reset() {this.$refs.form.resetFields();}, renderCards(cards) {let { renderRows } = this;return cards.map(card => {// 渲染name和children(renderRows) return (<el-card class="box-card" header={card.name}>{card.children && renderRows(card.children)}</el-card >)// 实现方式1// let h = this.$createElement;return h('el-card', { class: 'box-card' }, [h('template', { slot: 'header' }, [h('span', card.name)]),card.children && renderRows(card.children)]);// 实现方式2return (<el-card class="box-card"><template slot="header"><span>{card.name}</span></template>{card.children && renderRows(card.children)}</el-card >);})}},render() {const { title, items, rules, cards } = this.config;const { ruleForm, $scopedSlots: { btn } } = this;return (<div class="form-box">{title && <h2>{title}</h2>} <el-form ref="form" attrs={{ model: ruleForm, }} rules={rules} label-width="80px">{cards ? this.renderCards(cards) : this.renderRows(items)}</el-form> <div class="btn-bow">{btn ? btn({ t: '我是scopod' }) : (<div><el-button type="primary" onClick={e => this.doSubmit()}>提交</el-button><el-button onClick={e => this.reset()}>重置</el-button></div>)}</div> </div>)}
}
</script><style scoped>
.el-input,
.el-select,
.form-box .el-date-editor {width: 100%;
}:deep(.el-card__header) {text-align: left;
}.box-card {margin-bottom: 10px;
}
</style>

(1)声明表单类型 

// conf/uniTypes.js
export const  TEXT = 'text';
export const SELECT = 'select';
export const PASSWORD = 'password';
export const TEXTAREA = 'textarea';
export const RADIO = 'radio';
export const DATE_PICKER= 'datepicker';

 (2)封装深拷贝

// utils/index.jsexport const deepClone = (obj)=>{  // 处理环形对象带来的递归栈内存溢出let cache = new WeakMap(); // 避免强引用var objType = '[object Object]';function innerDeepClone(obj) {// 处理了基本数据类型  undefined null functionif (typeof obj !== 'object' || !obj) {return obj;}// obj不是方法的参数, 改变的this,由于不同类型的对象的type不同,// toString从不同this拿到的就不一样// var type = Object.prototype.toString.call(obj);if (cache.has(obj)){return cache.get(obj);}let tmp;// 处理非对象和数组if (obj instanceof Map) {tmp = new Map();cache.set(obj,tmp);obj.forEach((val, key) => {tmp.set(innerDeepClone(key), innerDeepClone(val))})} else if (obj instanceof Set) {tmp = new Set();cache.set(obj,tmp);obj.forEach(val => {tmp.add(innerDeepClone(val))})} else if (obj instanceof RegExp || obj instanceof Date) {tmp = new obj.constructor(obj);  cache.set(obj,tmp);} else {tmp = new obj.constructor();cache.set(obj,tmp);for (let key in obj) {tmp[key] = innerDeepClone(obj[key]);}}return tmp;}return innerDeepClone(obj)
}

2.使用公共表单组件

<template><div><GFormCreator :config="conf" @submit="createLoan"/><!-- <hr><GFormCreator ref="f2" :config="conf"><template #btn="{t}"><el-button @click="test1">提交{{ t }}</el-button></template></GFormCreator> --></div>
</template><script>
import conf from './loan-input-page'
import { createLoanApi } from '@/api/loan'
export default {methods: {async createLoan(user){let res = await createLoanApi(user);this.$notify.success('添加成功');},test2(data){console.log('数据:',data)},test1() {console.log(this.$refs.f2.getData())}},data() {return {conf}}
}
</script> 
/loan-input-page.js
import {TEXT,SELECT,PASSWORD,TEXTAREA,RADIO,DATE_PICKER
} from '@/conf/uiTypes';//性别
export const sexOptions = [{ value: "man", label: "男" },{ value: "woman", label: "女" }
];
//行业
export const companyOptions = [{ value: "education", label: "教育" },{ value: "finance", label: "金融" }
];
//婚否
export const marriageOptions = [{ value: "married", label: "已婚" },{ value: "unmarried", label: "未婚" }
];
//学历
export const educationOptions = [{ value: "college", label: "大学" },{ value: "highschool", label: "高中" }
];// 优化 => data方法中,默认是会Object.defineProperty => 当触发属性的get/set => 页面的更新export default Object.freeze({cards: [{name: "个人基本信息",children: [[{ label: "姓名", key: "name", type: TEXT },{ label: "出生日期", key: "birthday", type: DATE_PICKER },{label: "性别",key: "sex",type: SELECT,options: sexOptions}],[{ label: "身份证", key: "identity_card", type: TEXT }],[{label: "婚姻状态",key: "marriage",type: "select",options: marriageOptions},{label: "教育程度",key: "education",type: "select",options: educationOptions},{ label: "居住地址", key: "address1", type: TEXT }],[{ label: "户籍地址", key: "address2", type: TEXT },{ label: "居住电话", key: "phone", type: TEXT },{ label: "手机号", key: "mobile_phone", type: TEXT }]].map(row => row.map(item => ({ colspan: 8, ...item })))},{name: "职业信息",children: [[   // element原生属性{ label: "现职公司", key: "company", type: TEXT },{label: "所属行业",attrs: { placeholder: '请选择Green' },key: "trade",type: "select",options: companyOptions},{ label: "职位", key: "position", type: TEXT },{ label: "公司地址", key: "address3", type: TEXT }].map(item => ({ colspan: 6, ...item })),[{ label: "公司类型", key: "company_type", type: TEXT },{ label: "公司邮箱", key: "company_email", type: TEXT },{ label: "公司电话", key: "company_phone", type: TEXT }].map(item => ({ colspan: 8, ...item }))]},{name: "收支情况",children: [[{ label: "收支情况", key: "income", type: TEXT, colspan: 12 }]]},{name: "家庭联系人",children: [[{ label: "关系1", key: "contact", type: TEXT },{ label: "姓名", key: "contact_name", type: TEXT },{ label: "手机", key: "contact_phone", type: TEXT }].map(item => ({ colspan: 12, ...item }))]},{name: "工作证明人",children: [[{ label: "关系2", key: "contact2", colspan: 12, type: TEXT },{ label: "姓名", key: "contact2_name", colspan: 12, type: TEXT },{ label: "手机", key: "contact2_phone", colspan: 12, type: TEXT }],[{ label: "部门", key: "contact2_dep", colspan: 12, type: TEXT },{ label: "职位", key: "contact2_pos", colspan: 12, type: TEXT }],[{ label: "备注", key: "remark", type: "textarea" }]]}],rules: {name: [{ required: true, message: "请输入姓名", trigger: "blur" },{min: 2,max: 5,message: "长度在 2 到 5 个字符",trigger: "blur"}],identity_card: [{ required: true, message: "请输入身份证", trigger: "change" }],birthday: [{type: 'date',required: true,message: "请选择日期",trigger: "change"}],sex: [{ required: true, message: "请选择性别", trigger: "change" }],marriage: [{ required: true, message: "请选择婚姻状态", trigger: "change" }],education: [{ required: true, message: "请选择教育程度", trigger: "change" }],trade: [{ required: true, message: "请选择所属行业", trigger: "change" }],address1: [{ required: true, message: "请输入居住地址", trigger: "blur" }],address2: [{ required: true, message: "请输入户籍地址", trigger: "blur" }],phone: [{ required: true, message: "请输入居住电话", trigger: "blur" }],mobile_phone: [{ required: true, message: "请输入手机号", trigger: "blur" }],company: [{ required: true, message: "请输入现职公司全称", trigger: "blur" }],position: [{ required: true, message: "请输入职位", trigger: "blur" }],address3: [{ required: true, message: "请输入公司地址", trigger: "blur" }],company_type: [{ required: true, message: "请输入公司类型", trigger: "blur" }],company_email: [{ required: true, message: "请输入公司邮箱", trigger: "blur" }],company_phone: [{ required: true, message: "请输入公司电话", trigger: "blur" }],income: [{ required: true, message: "请输入收支情况", trigger: "blur" }],contact: [{ required: true, message: "请输入关系1", trigger: "blur" }],contact_name: [{ required: true, message: "请输入姓名", trigger: "blur" }],contact_phone: [{ required: true, message: "请输入手机", trigger: "blur" }],contact2: [{ required: true, message: "请输入关系2", trigger: "blur" }],contact2_name: [{ required: true, message: "请输入姓名", trigger: "blur" }],contact2_phone: [{ required: true, message: "请输入手机", trigger: "blur" }],contact2_dep: [{ required: true, message: "请输入部门", trigger: "blur" }],contact2_pos: [{ required: true, message: "请输入职位", trigger: "blur" }]},
}
)

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

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

相关文章

Mybatis的综合案例-学生信息查询系统 用于校验是否真正学习掌握了动态SQL

Mybatis的综合案例-学生信息查询系统 需求一&#xff1a;当用户输入的学生姓名不为空&#xff0c;则只根据学生信息进行查询; 当用户输入的学生姓名为空&#xff0c;且专业不为空&#xff0c;那么就根据学生专业进行学生的查询 需求二&#xff1a;查询所有id值小于5的学生信息…

List Label Standard Reporting Edition Crack

List & Label Standard Reporting Edition Crack List&Label是适用于所有主要开发平台的报告解决方案&#xff0c;提供了强大的报告引擎、灵活的API和功能丰富的报告设计器。只需要几行代码就可以在桌面、web或云应用程序中嵌入List&Label。它允许您的应用程序用户…

代码随想录训练营二刷第三天 | 203.移除链表元素 707.设计链表 206.反转链表

代码随想录训练营二刷第三天 | 203.移除链表元素 707.设计链表 206.反转链表 一、203.移除链表元素 题目链接&#xff1a;https://leetcode.cn/problems/remove-linked-list-elements/ 思路&#xff1a;使用虚拟头结点&#xff0c;两个指针&#xff0c;一个是遍历指针&#x…

天眼查接口 查询企业信息API 企查查接口

item_get-获得tyc详情 tyc.item_get 公共参数 请求地址: https://api-gw.cn/tyc/item_get 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff0…

Vue快速入门以及基础标签使用

目录 开始示例el挂载点data数据对象 vue基本标签v-textv-htmlv-on计数器示例实现v-showv-ifv-bind图片切换示例v-forv-on补充v-model axios网络请求axios基本使用vue中使用axios 开始示例 1.首先在html页面中引入vue的生产环境&#xff0c;在body标签中粘上下面代码 <scrip…

微客云直充卡券优惠话费充值接口开发稳定高效

微客云直充卡券话费 开发团队致力于此模块生命力至少3-5年 此模块以资源种类&#xff0c;官方直联接口为优势&#xff0c;不纯以软件更新为主&#xff0c;力争版本精准化服务用户 单独直充卡券话费系统&#xff0c;直接完成对各种消费场景的流量变现&#xff0c;更加开放与链路…

TCP--半连接队列和全连接队列

原文地址&#xff1a;https://plantegg.github.io/2020/04/07/%E5%B0%B1%E6%98%AF%E8%A6%81%E4%BD%A0%E6%87%82TCP–%E5%8D%8A%E8%BF%9E%E6%8E%A5%E9%98%9F%E5%88%97%E5%92%8C%E5%85%A8%E8%BF%9E%E6%8E%A5%E9%98%9F%E5%88%97–%E9%98%BF%E9%87%8C%E6%8A%80%E6%9C%AF%E5%85%AC%E…

arm:day6

实现UART通信&#xff1a; 1.键盘输入一个字符a,串口工具显示b 2.键盘输入一个字符串"nihao",串口工具显示"nihao" uart.h #ifndef __UART4_H__ #define __UART4_H__#include "stm32mp1xx_uart.h" #include "stm32mp1xx_gpio.h" #in…

4.物联网LWIP之C/S编程,stm32作为服务器,stm32作为客户端,代码的优化

LWIP配置 服务器端实现 客户端实现 错误分析 一。LWIP配置&#xff08;FREERTOS配置&#xff0c;ETH配置&#xff0c;LWIP配置&#xff09; 1.FREERTOS配置 为什么要修改定时源为Tim1&#xff1f;不用systick&#xff1f; 原因&#xff1a;HAL库与FREERTOS都需要使用systi…

Flink、Yarn架构,以Flink on Yarn部署原理详解

Flink、Yarn架构&#xff0c;以Flink on Yarn部署原理详解 Flink 架构概览 Apache Flink是一个开源的分布式流处理框架&#xff0c;它可以处理实时数据流和批处理数据。Flink的架构原理是其实现的基础&#xff0c;架构原理可以分为以下四个部分&#xff1a;JobManager、TaskM…

arm安装docker与docker-copose

一、银河麒麟Arm64安装docker 1、docker 安装包地址&#xff1a; https://download.docker.com/linux/static/stable 2、解压&#xff0c;然后将docker目录下文件拷贝到/usr/bin里 tar -xf docker-18.09.3.tgz mv docker/* /usr/bin/ 3、准备 docker.service系统配置文件 &…

[蓝帽杯 2022 初赛]domainhacker

打开流量包&#xff0c;追踪TCP流&#xff0c;看到一串url编码 放到瑞士军刀里面解密 最下面这一串会觉得像base64编码 删掉前面两个字符就可以base64解码 依次类推&#xff0c;提取到第13个流&#xff0c;得到一串编码其中里面有密码 导出http对象 发现最后有个1.rar文件 不出…

回归预测 | MATLAB实现BES-ELM秃鹰搜索优化算法优化极限学习机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现BES-ELM秃鹰搜索优化算法优化极限学习机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现BES-ELM秃鹰搜索优化算法优化极限学习机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效…

【已解决】记 Vue3+SpringBoot 前后端分离项目部署时的一次跨域问题

问题背景是在一次部署开发环境时&#xff0c;由于是前后端分离项目&#xff08;前端Vue3&#xff0c;后端SpringBoot&#xff09;&#xff0c;SpringBoot 使用 Docker 部署&#xff0c;前端访问服务接口时出现跨域问题。 不知道什么是跨域问题的小伙伴可以查看另一篇文章&…

二叉树中的最大路径和-递归

路径 被定义为一条从树中任意节点出发&#xff0c;沿父节点-子节点连接&#xff0c;达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root…

Spring 与【MyBatis 】和【 pageHelper分页插件 】整合

目录 一、Spring整合MyBatis 1. 导入pom依赖 2. 利用mybatis逆向工程生成模型层层代码 3. 编写配置文件 4. 注解式开发 5. 编写Junit测试类 二、AOP整合pageHelper分页插件 1. 创建一个AOP切面 2. Around("execution(* *..*xxx.*xxx(..))") 表达式解析 3. 编…

智慧互联,有序充电--多场景充电

企业微电网能效及充电管理解决方案 安科瑞 崔丽洁 1、企业需求&#xff08;目的地充电&#xff09; 站在企业的角度&#xff0c;除了要主动承担碳达峰、碳中和的社会责任&#xff0c;也需要考虑自身的经营和利润&#xff0c;需要结合企业的现状进行改造 企业微电网平台——与…

【QT5-自我学习-线程qThread练习-两种使用方式-1:通过继承线程类来使用-基础样例】

【QT5-自我学习-线程qThread练习-两种使用方式-1&#xff1a;通过继承线程类来使用-基础样例】 1、前言2、实验环境3-1、学习链接-参考文章3-2、先前了解-自我总结&#xff08;1&#xff09;线程处理逻辑事件&#xff0c;不能带有主窗口的事件&#xff08;2&#xff09;一般考虑…

【LeetCode75】第三十五题 统计二叉树中好节点的数目

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 给我们一棵二叉树&#xff0c;让我们统计这棵二叉树中好节点的数目。 那么什么是好节点&#xff0c;题目中给出定义&#xff0c;从根节点…

华为OD机试之报文重排序【Java源码】

题目描述 对报文进行重传和重排序是常用的可靠性机制&#xff0c;重传缓中区内有一定数量的子报文&#xff0c;每个子报文在原始报文中的顺序已知&#xff0c;现在需要恢复出原始报文。 输入描述 输入第一行为N&#xff0c;表示子报文的个数&#xff0c;0 &#xff1c;N ≤ …