封装公共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" }]},
}
)
相关文章:
封装公共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}}…...
List 分批处理
1.Google Guava <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.0.1-jre</version></dependency>List<String> tempList Arrays.asList("水星","金星&qu…...
SpringSession
Spring Session 是 Spring 的项目之一。Spring Session 提供了一套创建和管理 Servlet HttpSession 的方案,默认采用外置的 Redis 来存储 Session 数据,以此来解决 Session 共享的 问题。(springsession储存session数据的方式有很多,我们常…...
Python Web 开发之 JWT 简介
在之前的课程中,介绍过 Flask-Login 框架,它是基于 Session 和 Cookie 技术来实现用户授权和验证的,不过 Session 有很多的局限性,这一节介绍一种基于 token 的验证方式 —— JWT (JSON Web Token),除了对 JWT 的概念讲解之外&…...
科技资讯|荷兰电动自行车丢失将被拒保,苹果Find My可以减少丢失
荷兰最大的自行车协会荷兰皇家旅游俱乐部宣布,将不再为胖胎电动自行车提供保险,因为这种自行车的被盗风险极高。 随着电动自行车的销量飙升,胖胎也变得更受欢迎。但问题是,胖胎电动自行车也成为了自行车盗窃者的首选目标。ANWB …...
debian rules语法
当创建Debian软件包时,debian/rules 文件是非常重要的,它定义了软件包的构建规则。这个文件使用Makefile语法,指导构建、编译和安装软件包。下面将详细地介绍debian/rules文件的语法和常见用法。 基本结构: 一个简单的debian/rul…...
网易2023年Q2财报:营收240亿元,游戏技术跨产业创造数字就业
8月24日,网易发布2023年Q2财报。二季度,网易继续聚焦主营业务,业绩表现稳健;净收入240亿元,非公认会计准则下归属于公司股东的持续经营净利润90亿元,研发投入39亿元,相当于拿出近一半利润投入研…...
Python的Flask框架创建、运行与访问
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
Java课题笔记~ 综合案例
3.综合案例 3.1 功能介绍 以上是我们在综合案例要实现的功能。除了对数据的增删改查功能外,还有一些复杂的功能,如 批量删除、分页查询、条件查询 等功能 批量删除 功能:每条数据前都有复选框,当我选中多条数据并点击 批量删除 按…...
Seaborn数据可视化(二)
目录 1.Seaborn风格设置 1.1 主题设置 1.2 轴线设置 1.3 移除轴线 1.4 使用字典传递函数 2.设置绘图元素比例 2.1 设置绘图元素比例paper 2.2 设置绘图元素比例poster 2.3 设置绘图元素比例notebook Seaborn将Matplotlib的参数划分为两个独立的组合,第一组用于…...
HDLBits-Verilog学习记录 | Verilog Language-Basics(1)
文章目录 3.Simple wire4.Four wires5.inverter | Notgate6. And gate7.Nor gate8.Xnorgate 3.Simple wire problem:Create a module with one input and one output that behaves like a wire. module top_module( input in, output out );assign out in;endmodule4.Four w…...
elementui表格嵌套上传文件直传到oss服务器(表单上传)
提示:记录项目中遇到的问题,仅供参考 文章目录 前言一、vue代码二、js接口请求代码 前言 项目需求是在表格中嵌套一个上传图片的功能,并且回显选择的图片和已上传的图片,再通过点击操作列中上传按钮才开始上传,使用的…...
使用navicat来访问doris
访问Doris的UI http:// dorisfe_ip:8030 由于doris是使用mysql协议,因此可以不用任何额外配置就可以使用navicat访问doris。 可以使用MySql客户端来连接Doris FE,也可以使用mysql命令工具连接,因为他是Mysql协议,所以在使用上跟M…...
2023国赛数学建模思路 - 案例:异常检测
文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…...
redis实战-缓存三剑客穿透击穿雪崩解决方案
缓存穿透 定义 缓存穿透 :缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,造成数据库压力,也让缓存没有发挥出应有的作用 解决方案 缓存空对象 当我们客户端…...
Tomcat10安装及配置教程win11
Tomcat10安装及配置教程win11 Tomcat下载链接 Tomcat官网 Tomcat官网地址 https://tomcat.apache.org/ Tomcat的版本列表 点击上图中左侧红框内**Which version?**即可得下图 下载Tomcat 点击上图中左侧红框内红框内tomcat版本即可得下图,下载zip包 解压zip包…...
遗传算法解决TSP问题
一、求解问题概述 1.1 TSP问题 TSP问题是指旅行商问题(Traveling Salesman Problem)。在TSP问题中,假设有一名旅行商要在给定的一组城市之间进行旅行,每个城市只能被访问一次,并且旅行商必须最终返回出发城市。问题的…...
设计模式-工厂设计模式
核心思想 在简单工厂模式的基础上进一步的抽象化具备更多的可扩展和复用性,增强代码的可读性使添加产品不需要修改原来的代码,满足开闭原则 优缺点 优点 符合单一职责,每个工厂只负责生产对应的产品符合开闭原则,添加产品只需添…...
TM4C123库函数学习(3)---串口中断
前言 (1)学习本文之前,需要先学习前两篇文章。 (2)学习本文需要准备好TTL转USB模块。 函数介绍 ROM_GPIOPinConfigure() 配置GPIO引脚的复用功能。因为引脚不可能只有一个输出输入作用…...
opencv 进阶13-Fisherfaces 人脸识别-函数cv2.face.FisherFaceRecognizer_create()
Fisherfaces 人脸识别 PCA 方法是 EigenFaces 方法的核心,它找到了最大化数据总方差特征的线性组合。不可否认,EigenFaces 是一种非常有效的方法,但是它的缺点在于在操作过程中会损失许多特征信息。 因此,在一些情况下,…...
基于mysql5.7制作自定义的docker镜像,适用于xxl-job依赖的数据库,自动执行初始化脚本(ddl语句和dml语句)
一、背景 xxl-job-admin依赖mysql数据库,且需执行初始化脚本,包括ddl和dml语句。 具体的步骤总结如下: 1、新建数据库xxl_job2、创建mysql表table3、执行dml语句,包括新建admin用户及密码,创建执行器和任务。 毫无疑…...
LeetCodeHot100python版本:单调栈,栈,队列,堆
单调栈 739. 每日温度 42. 接雨水 双指针 单调栈(横向求解) 84. 柱状图中最大的矩形 栈和队列 队列:先入先出 栈:先入后出 两个栈 模拟 队列 一个队列 可以模拟 栈 20. 有效的括号 155. 最小栈 394. 字符串解码 堆 215. 数组中的第K个最大元素 3…...
JUC初识
JUC 是什么 java.util.concurrent 在并发编程中使用的工具包 从线程start 开始 package com.jhj.Thread;public class ThreadDemo {public static void main(String[] args) {Thread t1 new Thread(() -> {}, "t1");t1.start();} }start 方法调的是native sta…...
stm32之5.长按按键(使用时钟源)调整跑马灯速度
------------------------------ 源码 #include <stm32f4xx.h> #include "led.h" #include "delay.h" #include "my_str.h" #include "beep.h" #include "key.h" int main(void) { key_init(); Led_init();…...
element ui datePick时间日期一段时间,限制选择日期的范围
想限制只能选日期间隔为一年,联合选择器样式不好改,使用俩单独的 有两个办法限制 1.一个在外层使用form通过表单验证控制,出现错误提示(由于是两个单独的组件,触发验证的方式又为单个失去焦点,所以俩组件…...
kubernetes--技术文档-真--集群搭建-三台服务器一主二从(非高可用)-三服务器位于同交换机中
在使用k8s之前如果不太熟悉k8s的可以先看这个文章: kubernetes--技术文档--基本概念--《10分钟快速了解》_一单成的博客-CSDN博客 三节点相同安装操作: 1、设置hosts解析 根据角色在三个服务器中运行,设置自己的hostname。 标识…...
高性能MySQL实战(三):性能优化
大家好,我是 方圆。这篇主要介绍对慢 SQL 优化的一些手段,而在讲解具体的优化措施之前,我想先对 EXPLAIN 进行介绍,它是我们在分析查询时必要的操作,理解了它输出结果的内容更有利于我们优化 SQL。为了方便大家的阅读&…...
198. 打家劫舍
题目 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放…...
Pydev·离线git包
Pydev离线git包 1.下载离线git包:eclipse.egit.repository-4.4.0.201606070830-r.zip 2.将解压后目录:eclipse.egit.repository-4.4.0.201606070830-r\plugins下的jar文件放到 ide\eclipse\plugins目录下 3.重启pydevIDE 百度搜索站长工具:h…...
Vue-12.集成postcss.config.js
PostCSS 介绍 PostCSS 是一个用于处理样式的工具,可以通过插件来定制其行为。以下是一些常用的 PostCSS 插件和 API 的介绍: Autoprefixer: 这是一个流行的 PostCSS 插件,用于自动添加浏览器前缀,以确保您的样式在不同浏览器中具…...
行业前10的网站建设公司/四川seo平台
应用情形1.员工a在 master 主分支上新建一个 newBranch 分支,然后开始在 newBranch 分支上开始编写代码。编写完成后将该分支提交到远程库。2.项目经理b在远程库上拉取 newBranch 分支,查看代码无误后将 newBranch 分支合并到 master 主分支,…...
扫二维码直接进网站怎么做/有没有可以代理推广的平台
Android提供了调试工具被称为Dalvik Debug Monitor Server (DDMS),工作原理如下: DDMS将搭建起IDE与测试终端(Emulator 或者connected device)的链接,它们应用各自独立的端口监听调试器的信息,DDMS可以实时监测到测试终端的连接情…...
做网站学多长时间可以学会/软文代写公司
好啦,101-200的文章阶段记录开始啦,新的开始,加油! 上一篇文章写到了递归遍历所有文件,提到了压缩包的问题,现在就来介绍一下: python解压缩文件常用shutil模块 直接上代码: 压缩…...
ps做网站页面设置为多大/搜狗权重查询
一、客户端 (一)登录获取token (二)超时后报token过期 登录超时,路由从定向到登录页 二、服务端 (一) 登录接口颁发token (二)每个请求接口前,进行鉴权校验 1.鉴权 2.接口 Pyth…...
会唐网做网站/宁波seo公司
夜光序言: 长夜沉沉雾泛泛 点滴浸青衫 君居北海、我独南 无人卷珠帘 亦无人丈衣宽 “三月春风不渡玉门关” 正文: 夜光:还是不打字了~~打字比较不清晰,截图更直观~~ response对象 Response动态响应 Response重定向...
防腐木用什么名字做网站/网络营销专业课程
计算机汇编语言入门微处理器体系结构基本微处理器设计由时钟同步所有CPU 操作控制器(CU) 协调各执行步骤的顺序运算器(ALU) 进行算术运算和逐位处理时钟同步所有CPU 和总线操作机器(时钟)周期是完成单个操作的时间时钟用来触发事件指令执行周期取指令译码取操作数执行指令输出存…...