我们在日常工作中,经常遇到多条件的筛选或者是多数据的form,一条一条写起来太费时间+精力,二次封装form之后会大大节省我们的时间,我采用的方法是jsx,render中生成form的形式,废话不多说,直接上代码
1.首先是子组件proform
<script lang="jsx">
import {
Button,
Form,
FormItem,
Input,
InputNumber,
Row,
Col,
DatePicker,
TimePicker,
} from "element-ui";
import Select from "./components/ProSelect.vue";
import RadioGroup from "./components/ProRadioGroup.vue";
import CheckboxGroup from "./components/ProCheckboxGroup.vue";
const componentsMap = {
Input,
InputNumber,
Select,
RadioGroup,
CheckboxGroup,
DatePicker,
TimePicker,
};
export default {
props: {
labelWidth: {
type: String,
default: ''
},
labelPosition: {
type: String,
default: "left",
},
gutter: {
type: Number,
default: 15
},
schemas: {
type: Array,
default: () => [],
},
formData: {
type: Object,
default: () => ({}),
},
model: Object,
},
created() {
this.datas = this.schemas.slice(0, 3);
},
data() {
return {
flag: true,
datas: [],
};
},
methods: {
reset() {
this.$refs.formRef.resetFields();
},
validate() {
return this.$refs.formRef
.validate()
.then(() => {
return this.model;
})
.catch((err) => {
return Promise.reject(err);
});
},
},
render(h) {
const { schemas, labelWidth, labelPosition, gutter, model } = this;
return (
<Form
props={{ model: this.model }}
labelWidth={labelWidth + "px"}
labelPosition={labelPosition}
ref="formRef"
>
{/* {
{
scopedSlots:{
default: ()=>{
},
header: ()=>{
}
},
}
} */}
<Row gutter={gutter}>
{this.datas.map((item) => {
const rules = [];
if (item.required) {
rules.push({ required: true, message: `${item.label}不能为空` });
}
return (
<Col span={item.span}>
<FormItem label={item.label} prop={item.field} rules={rules}>
{h(componentsMap[item.component], {
props: {
...item.componentProps,
value: this.model[item.field],
},
on: {
input: (newValue) => {
this.model[item.field] = newValue;
},
},
})}
</FormItem>
</Col>
);
})}
<Col span={6}>
<FormItem>
<Button type="primary" onClick={this.validate}>
查询
</Button>
<Button onClick={this.reset}>重置</Button>
{schemas.length > 3 ? (
<span>
{this.flag ? (
<Button type="text" icon="el-icon-arrow-down"
onClick={() => {
this.flag = false;
this.datas = this.schemas;
}}
>
展开
</Button>
) : (
<Button type="text" icon="el-icon-arrow-up"
onClick={() => {
this.flag = true;
this.datas = this.schemas.slice(0, 3);
}}
>
收起
</Button>
)}
</span>
) : (
<div></div>
)}
</FormItem>
</Col>
</Row>
</Form>
);
},
};
</script>
<style scoped lang="scss">
::v-deep {
.el-form-item {
width: 100%;
display: flex;
.el-form-item__content {
flex: 1;
}
.el-form-item__label {
flex-shrink: 0;
padding-right: 12px;
}
}
.el-col {
padding: 0 8px;
}
.el-date-editor,
.el-select,
.el-input {
width: 100%;
}
.el-button {
margin-right: 10px;
}
}
</style>
2.然后二次封装其他基础组件比如el-select,el-radio
<script lang="jsx">
import { Select, Option } from 'element-ui'
export default {
props: {
value: [String, Array],
options: {
type: Array,
default: () => []
},
multiple: {
type:Boolean
}
},
data() {
return {}
},
computed: {
model: {
get() {
return this.value
},
set(newVal) {
this.$emit('input', newVal)
}
}
},
render(h) {
const { model, options, multiple} = this
return (
<Select vModel={this.model} clearable multiple={multiple}>
{options.map((item) => {
return <Option label={item.label} value={item.value}></Option>
})}
</Select>
)
}
}
</script>
<script lang="jsx">
import { Radio, RadioGroup} from 'element-ui'
export default {
props: {
value: [String, Array],
options: {
type: Array,
default: () => []
}
},
data() {
return {}
},
computed: {
model: {
get() {
return this.value
},
set(newVal) {
this.$emit('input', newVal)
}
}
},
render(h) {
const { model, options } = this
return (
<RadioGroup vModel={this.model}>
{options.map((item) => {
return <Radio label={item.label} value={item.value}></Radio>
})}
</RadioGroup>
)
}
}
</script>
<script lang="jsx">
import { CheckboxGroup, Checkbox } from 'element-ui'
export default {
props: {
value: Array,
options: {
type: Array,
default: () => []
}
},
data() {
return {
}
},
computed: {
model: {
get() {
return this.value
},
set(newVal) {
this.$emit('input', newVal)
}
}
},
render(h) {
const { model, options } = this
return (
<CheckboxGroup vModel={this.model}>
{
options.map(item => {
return (
<Checkbox label={item.label} value={item.value}>
{item.label}
</Checkbox>
)
})
}
</CheckboxGroup>
)
}
}
</script>
3.最后父组件引入子组件使用,并传入json
<template>
<div class="wapper">
<ProForm
ref="form"
form-ref="freeForm"
:model="formData"
v-bind="formConfig"
:rules="rules"
/>
</div>
</template>
<script>
import { ProForm } from './ProForm '
export default {
components: {
ProForm,
},
data() {
return {
// 表单数据console
formData: {
username: "",
number: 0,
time: "",
orgIdProduction: "",
sex: "",
love: [],
developmentMethods: "",
},
// el-form-item 配置项
formConfig: {
// labelWidth: 100, // 标题宽度
labelPosition: "left",
gutter: 12,
schemas: [
{
required: true,
label: "用户名",
field: "username",
component: "Input", // el-input可以省略,默认使用el-input
placeholder: "请输入用户名", // placeholder可以省略,默认显示“请输入+label”
span: 6, // 使用栅格布局
},
{
label: "数字输入",
field: "number",
component: "InputNumber",
controlsPosition: "right",
span: 6, // 使用栅格布局
},
{
label: "所属单位",
labelWidth: 180, // 标题宽度-优先级高
component: "Select",
field: "orgIdProduction",
span: 6,
componentProps: {
multiple: true, // 是否多选
clearable: true, // 能否清空
placeholder: "请选择",
options: [
{
label: "白庄煤矿",
value: "01076430",
},
{
label: "梁宝寺煤矿",
value: "01076323",
},
],
},
onChange: (value) => {
console.log(value);
},
},
{
label: "日期选择",
field: "time",
component: "DatePicker",
type: "datetime",
span: 6,
componentProps: {
width: "100%",
},
},
{
label: "性别",
field: "sex",
span: 6, // 支持栅格布局
component: "RadioGroup", // 可以传入任意组件
componentProps: {
options: [
{
label: "男",
value: 1,
},
{
label: "女",
value: 2,
},
],
},
onChange: (e) => {
console.log(e);
},
},
{
label: "菜单",
field: "developmentMethods",
span: 6,
component: "RadioGroup",
componentProps: {
options: [
{
label: "菜单1",
value: "menu1",
},
{
label: "菜单二",
value: "menu2",
},
],
onChange: (e) => {
console.log(e);
},
},
},
{
label: "兴趣爱好",
field: "love",
span: 6, // 支持栅格布局
component: "CheckboxGroup", // 可以传入任意组件
componentProps: {
options: [
{
label: "读书",
value: 1,
},
{
label: '菜单二',
value: 'menu2'
}
]
}
}
]
},
addFormConfig: {
labelWidth: 100, // 标题宽度
labelPosition: 'left',
gutter: 12,
schemas: [
{
label: '用户名',
field: 'username',
component: 'Input', // el-input可以省略,默认使用el-input
placeholder: '请输入用户名' // placeholder可以省略,默认显示“请输入+label”
},
{
label: '数字输入',
field: 'number',
component: 'InputNumber',
controlsPosition: 'right'
},
{
label: '所属单位',
labelWidth: 180, // 标题宽度-优先级高
component: 'Select',
field: 'orgIdProduction',
componentProps: {
multiple: true, // 是否多选
placeholder: '请选择',
options: [
{
label: '白庄煤矿',
value: '01076430'
},
{
label: '梁宝寺煤矿',
value: '01076323'
}
]
},
onChange: (value) => {
console.log(value)
}
},
{
label: '日期选择',
field: 'time',
component: 'DatePicker',
type: 'datetime',
componentProps: {
width: '100%'
}
},
{
label: '性别',
field: 'sex',
component: 'RadioGroup', // 可以传入任意组件
componentProps: {
options: [
{
label: '男',
value: 1
},
{
label: '女',
value: 2
}
]
},
onChange: (e) => {
console.log(e)
}
},
{
label: '兴趣爱好',
field: 'love',
component: 'CheckboxGroup', // 可以传入任意组件
componentProps: {
options: [
{
label: '读书',
value: 1
},
{
label: '写字',
value: 2
},
{
label: '听歌',
value: 4
}
]
},
onChange: (e) => {
console.log(e)
}
},
{
label: '菜单',
field: 'developmentMethods',
component: 'RadioGroup',
isButton: true,
clearable: true,
hidden: true,
componentProps: {
options: [
{
label: '菜单1',
value: 'menu1'
},
{
label: '菜单二',
value: 'menu2'
}
]
}
}
]
},
// el-form-item 验证规则
};
},
methods: {
// 级联类型
changeMajor(type) {
const json = {
primary: [
{
label: "数学",
value: 1,
},
{
label: "语文",
value: 2,
},
],
junior: [
{
label: "英语",
value: 5,
},
{
label: '生物',
value: 7
}
]
}
},
openAddFormModal() {
DetailFormModal.show({
title: '新增数据',
schemas: this.addFormConfig.schemas,
formData: this.formData
}).then(res => {
console.log('openAddFormModal', res)
})
}
}
}
</script>
<style>
.wapper {
background: #fff;
}
</style>
最后:展示效果:
希望能对你有帮助