前两天封装了一个基于vue和Element的table表格组件,阅读的人还是很多的,看来大家都是很认同组件化、高复用这种开发模式的,毕竟开发效率高,代码优雅,逼格高嘛。虽然这两天我的心情很糟糕,就像“懂王”怼记者:“你是一个糟糕的记者;CNN,Fake news”一样的心情,但我还是忍着难受的心情来工作和分享,毕竟工作是饭碗,分享也能化解我糟糕透顶的心情。

今天,就来分享一下基于vue和Element所封装的form表单组件,其中所用到的技术,在上一篇文章封装Vue Element的table表格组件中已介绍的差不多了,今天再来多讲一个vue的动态组件component,关于动态组件component的介绍,vue官方倒是很吝啬,就只是给了一个例子来告诉我们如何使用而已。我们可以把它理解成一个占位符,其具体展示什么,是有isattribute来实现,比如官网给的例子:

<component v-bind:is="currentTabComponent"></component>

在上述示例中,currentTabComponent可以包括:

  • 已注册组件的名字

  • 或一个组件的选项对象

就酱,对它的介绍完了。

如果你还想了解更多,可以去vue官网查看。

接下来就是封装的具体实现,照例先来张效果图:



1、封装的form表单组件Form.vue:

<template>
<el-form ref="form" :model="form" :rules="rules" size="small" :label-position="'top'">
<el-row :gutter="20">
<el-col :lg="8" :md="12" :sm="24" v-for="(x, i) in formItems" :key="i">
<el-form-item :label="x.label" :prop="x.prop">
<component v-model="form[x.prop]" v-bind="componentAttrs(x)" class="width-full" />
</el-form-item>
</el-col>
</el-row>
<div class="searchBtn">
<el-button class="filter-item" @click="reset">重置</el-button>
<el-button class="filter-item" type="primary" @click="submit">查询</el-button>
</div>
</el-form>
</template> <script>
import { fromEntries } from '@/utils'
export default {
props: {
config: Object,
},
components: {
selectBar: {
functional: true,
props: {value: String, list: Array, callback: Function},
render(h, {props: {value = '', list = [], callback}, data: {attrs = {}}, listeners: {input}}){
return h('el-select', {class: 'width-full', props: {value, ...attrs}, on: {change(v) {input(v); callback(v)}}}, list.map(o => h('el-option', {props: {...o, key: o.value}})))
}
},
checkbox: {
functional: true,
props: {value: Boolean, desc: String },
render(h, {props: {value = '', desc = ''}, data: {attrs = {}}, listeners: {input}}){
return h('el-checkbox', {props: {value, ...attrs}, on: {change(v) {input(v)}}}, desc)
}
},
checkboxGroup: {
functional: true,
props: {value: Array, list: Array},
render(h, {props: {value = [], list = []}, data: {attrs = {}}, listeners: {input}}){
return h('el-checkbox-group', {props: {value, ...attrs}, on: {input(v) {input(v)}}}, list.map(o => h('el-checkbox', {props: {...o, label: o.value, key: o.value}}, [o.label])))
}
},
radioGroup: {
functional: true,
props: {value: String, list: Array },
render(h, {props: {value = '', list = []}, data: {attrs = {}}, listeners: {input}}){
return h('el-radio-group', {props: {value, ...attrs}, on: {input(v) {input(v)}}}, list.map(o => h('el-radio', {props: {...o, key: o.label}}, [o.value])))
}
},
},
data(){
let { columns, data } = this.config; return {
TYPE: {
select: {
is: 'selectBar',
clearable: true, //是否可清空,默认为false不可清空
},
text: {
is: 'el-input',
clearable: true,
},
switch: {
is: 'el-switch',
},
checkbox: {
is: 'checkbox',
clearable: true,
},
checkboxGroup: {
is: 'checkboxGroup',
clearable: true,
},
radioGroup: {
is: 'radioGroup',
clearable: true,
},
daterange: {
is: 'el-date-picker',
type: 'daterange',
valueFormat: 'yyyy-MM-dd',
rangeSeparator: '至',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
editable: false,
},
date: {
is: 'el-date-picker',
type: "date",
valueFormat: 'yyyy-MM-dd',
editable: false,
},
auto: {
is: 'el-autocomplete'
}
},
form: columns.reduce((r, c) => Object.assign(r, {[c.prop]: data[c.prop] ? data[c.prop] : (c.is == 'checkboxGroup' ? [] : null)}), {}),
rules: columns.reduce((r, c) => ({...r, [c.prop]: c.rules ? c.rules : []}), {}),
}
},
computed: {
formItems() {
return this.config.columns;
},
},
methods: {
componentAttrs(item) {
let {is = 'text', label} = item, map = fromEntries(Object.entries(item).filter(n => !/^(label|prop|is|rules)/.test(n[0]))),
placeholder = (/^(select|el-date-picker)/.test(is) ? '请选择' : '请输入') + label; return {...map, ...this.TYPE[is], placeholder}
},
reset() {
this.$refs.form.resetFields();
},
submit() {
this.$refs.form.validate(valid => valid && this.$emit('submit', this.form));
},
geRules(){
let rules = {};
this.config.columns.forEach(c => {
let {prop, rules: ruleList = [], required = false} = c;
rules[prop] = ruleList;
required && ruleList.unshift({required, message: `${c.label}不能为空`});
})
return { rules };
},
}
};
</script> <style scoped>
.width-full{width: 100%;}
</style>

在封装时有一个Object.fromEntries的方法不兼容ie,而我们公司又要求项目可以兼容ie(我们公司的ie基本都是ie11),所以只能自己封装了一个fromEntries方法。

export const fromEntries = arr => {
if (Object.prototype.toString.call(arr) === '[object Map]') {
console.log(1)
let result = {};
for (const key of arr.keys()) {
result[key] = arr.get(key);
} return result;
} if(Array.isArray(arr)){
let result = {}
arr.map(([key,value]) => {
result[key] = value
}) return result
}
throw 'Uncaught TypeError: argument is not iterable';
}

2、使用已封装的表单组件:

<template>
<Form :config="config" @submit="getList" ref="form" />
</template> <script>
import Form from "./Form"; const statusLlist = [
{label: '未提交', value: "0"},
{label: '待审批', value: "1"},
{label: '已通过', value: "2", disabled: true}
] export default {
components: {
Form,
},
data() {
const confimPass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.$refs.form.form.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
}; return {
config: {
columns: [
{ prop: "name", label: "借款人名称", is: "auto", fetchSuggestions: this.querySearch },
{ prop: "certificateId", label: "统一信用代码", rules: [{required: true, message: '请输入统一信用代码'}] },
{ prop: 'date', label: "日期", is: 'date', },
{ prop: 'status', label: "状态", is: 'select', list: statusLlist, callback: r => this.statusChange(r) },
{ prop: "password", label: "密码", type: 'password' },
{ prop: "confimPass", label: "确认密码", type: 'password', rules: [{validator: confimPass}] },
{ prop: 'remark', label: "备注", type: 'textarea' },
{ prop: "email", label: "邮箱", rules: [{ required: true, message: '请输入邮箱地址' }, { type: 'email', message: '请输入正确的邮箱地址' }] },
{ prop: 'love', label: '爱好', is: 'checkboxGroup', list: [{label: '篮球', value: "0"}, {label: '排球', value: "1"}, {label: '足球', value: "2", disabled: true}] },
],
data: {
name: '小坏',
certificateId: '222',
status: '0',
love: ['0']
}
},
}
},
methods: {
querySearch(q, cb){
if (!q) {cb([]);return}
},
getList(res){
console.log(res)
},
statusChange(r){
console.log(r)
},
},
}
</script>

本次封装的form表单组件,基本考虑到了在日常开发中会经常使用到的表单组件,如果还有其他的需求,可自行添加。另外,本次封装也对表单的回显(返显)做了实现,比如我们在编辑数据时,需要将被修改的数据显示在表单中,本次封装就充分考虑到了这一点,只要你在传给封装的form组件的参数中加一个data参数,并将需要回显的数据名称一一对应并赋值就可以了。

封装Vue Element的form表单组件的更多相关文章

  1. 封装react antd的form表单组件

    form表单在我们日常的开发过程中被使用到的概率还是很大的,比如包含了登录.注册.修改个人信息.新增修改业务数据等的公司内部管理系统.而在使用时这些表单的样式如高度.上下边距.边框.圆角.阴影.高亮等 ...

  2. Vue + Element-ui实现后台管理系统(5)---封装一个Form表单组件和Table表格组件

    封装一个Form表单组件和Table组件 有关后台管理系统之前写过四遍博客,看这篇之前最好先看下这四篇博客.另外这里只展示关键部分代码,项目代码放在github上: mall-manage-syste ...

  3. Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)

    Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成) 动态表单生成 ElementUI官网引导 Element表单生成 Element动态增减表单,在线代码 关键配置 templa ...

  4. Form( 表单) 组件

    本节课重点了解 EasyUI 中 Form(表单)组件的使用方法, 这个组件不依赖于任何组件.一. 加载方式表单组件只能在 JS 区域设置,首先定义一张表单.<form id="box ...

  5. 第二百二十一节,jQuery EasyUI,Form(表单)组件

    jQuery EasyUI,Form(表单)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 Form(表单)组件的使用方法,这个组件不依赖于 ...

  6. Django form表单 组件

    目录 Django form表单 组件 Form 组件介绍 普通方式手写注册功能 使用form组件实现注册功能 Form 常用字段与插件 常用字段(必备) 字段参数(必备) 内置验证(必备) 自定义效 ...

  7. Vue 2.x折腾记 - (17) 基于Ant Design Vue 封装一个配置式的表单组件

    前言 写了个类似上篇搜索的封装,但是要考虑的东西更多. 具体业务比展示的代码要复杂,篇幅太长就不引入了. 效果图 2019-04-25 添加了下拉多选的渲染,并搜索默认过滤文本而非值 简化了渲染的子组 ...

  8. 从后端到前端之Vue(六)表单组件

    表单组件 做项目的时候会遇到一个比较头疼的问题,一个大表单里面有好多控件,一个一个做设置太麻烦,更头疼的是,需求还总在变化,一会多选.一会单选.一会下拉的,变来变去的烦死宝宝了. 那么怎么解决这个问题 ...

  9. vue3 element-plus 配置json快速生成form表单组件,提升生产力近600%(已在公司使用,持续优化中)

    ️本文为博客园社区首发文章,未获授权禁止转载 大家好,我是aehyok,一个住在深圳城市的佛系码农‍♀️,如果你喜欢我的文章,可以通过点赞帮我聚集灵力️. 个人github仓库地址: https:gi ...

随机推荐

  1. MySQL数据管理

    3.MySQL数据管理 3.1外键 方式一:  create table `grade`(  `gradeid` int(10) not null auto_increment comment '年纪 ...

  2. 旧的成功的AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="htt ...

  3. 第四章 常用API(下)

    4.1.String类 描述:该类代表字符串 构造方法: 方法 描述 public String() 初始化构造一个空白字符串 public String(char[] value) 通过字符数组初始 ...

  4. org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/book]] Tomcat ServletXml 异常

    此异常是因为xml配置serlvet-url-pattern缺少’/’     应该改为 /regist   背景: 写了base标签 form表单的action属性的值   个人分析: ️表单提交时 ...

  5. Day01_虚拟化架构与系统部署

    学于千峰教育开源课程 感恩 千峰教育官网 b站在线视频 前言:本人所使用的操作系统是MacOS 使用的虚拟机软件为parallels desktop 本章结构 构建桌面端虚拟环境 虚拟机的概述 VMa ...

  6. PHP array_udiff_assoc() 函数

    实例 比较两个数组的键名和键值(使用内建函数比较键名,使用用户自定义函数比较键值),并返回差集: <?phpfunction myfunction($a,$b){if ($a===$b){ret ...

  7. CF321E Ciel and Gondolas Wqs二分 四边形不等式优化dp 决策单调性

    LINK:CF321E Ciel and Gondolas 很少遇到这么有意思的题目了.虽然很套路.. 容易想到dp \(f_{i,j}\)表示前i段分了j段的最小值 转移需要维护一个\(cost(i ...

  8. log4j2 自动删除过期日志文件配置及实现原理解析

    日志文件自动删除功能必不可少,当然你可以让运维去做这事,只是这不地道.而日志组件是一个必备组件,让其多做一件删除的工作,无可厚非.本文就来探讨下 log4j 的日志文件自动删除实现吧. 0. 自动删除 ...

  9. java -jar .jar中没有主清单属性

    pom里加上 <build> <plugins> <plugin> <groupId>org.springframework.boot</grou ...

  10. Redis 超详细总结笔记总

    作者 | 王爷科技 来源 | www.toutiao.com/i6713520017595433485 1. Redis 简介 Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key ...