有时候常常需要二次封装一下Element UI里面的一些东西来满足开发是的一些需求,为了方便 快捷的适应开发,就封装了常用的组件之一中的表单。
由于个人水平比较菜,然后又想方便以后快速开发(其实就是想摸鱼)。最后🐟没摸成,还有点小费事。废话不多说,上代码:
// 模板部分
<el-form
:label-width="formConfig.labelWidth"
:label-position="formConfig.labelPosition"
:ref="formConfig.ref"
:model="formParams"
:inline="formConfig.inline"
>
<el-form-item
:label="item.label"
v-for="(item, index) in formDataList"
:key="index"
:prop="item.prop"
:rules="item.rules"
>
<el-input
v-if="item.type === 'input'"
v-model="formParams[item.prop]"
:placeholder="item.placeholder"
></el-input>
<el-select
v-if="item.type === 'select'"
style="width: 100%"
v-model="formParams[item.prop]"
:placeholder="item.placeholder"
>
<el-option
:label="opItem.label"
:value="opItem.value"
v-for="(opItem, index) in item.options"
:key="index"
></el-option>
</el-select>
<el-date-picker
v-if="item.type === 'date'"
type="date"
value-format="yyyy-MM-dd"
style="width: 100%"
v-model="formParams[item.prop]"
:placeholder="item.placeholder"
></el-date-picker>
<el-date-picker
v-if="item.type === 'daterange'"
type="daterange"
value-format=“yyyy-MM-dd”
style="width: 100%"
start-placeholder="开始时间"
end-placeholder="结束时间"
v-model="formParams[item.prop]"
></el-date-picker>
<el-radio-group
v-if="item.type === 'radio'"
v-model="formParams[item.prop]"
:placeholder="item.placeholder"
>
<el-radio
:label="opItem.label"
v-for="(opItem, index) in item.options"
:key="index"
:rules="item.rules"
></el-radio>
</el-radio-group>
<el-input
v-if="item.type === 'textarea'"
type="textarea"
v-model="formParams[item.prop]"
:placeholder="item.placeholder"
></el-input>
<el-switch
v-if="item.type === 'switch'"
v-model="formParams[item.prop]"
></el-switch>
</el-form-item>
</el-form>
<div>
<!-- 插槽、为了多变的存放操作按钮 -->
<template>
<slot name="operation"></slot>
</template>
</div>
<script>
export default {
/**
* formDataList 表单数据
* formParams 表单value /prop
* formConfig 表单配置值
*/
props: {
formDataList: {
type: Array,
default: () => [],
},
formParams: {
type: Object,
default: () => {},
},
formConfig: {
type: Object,
default: () => {},
}
},
methods: {
// 从外部验证表单是否必填项满足条件
validated(callback) {
this.$refs[this.formConfig.ref].validate((valid) => {
callback();
});
},
// 将子组件的表单内容传递给父表单
transferData() {
return new Promise((resolve, reject) => {
this.$refs[this.formConfig.ref].validate((valid) => {
if (valid) {
resolve(this.formParams);
} else {
reject("err");
}
});
});
},
},
};
</script>
其中在使用validated,transferData 这两个方法在使用的时候切记、切记:父组件一定要有一个跟子组件一样的ref值,不然的话是
无效的。就像下面这样去调用组件:
<template>
<div class="content">
<!-- 如果父组件想要使用子组件中的transferData、validated方法去获取或是验证表单的内容,就要加上ref,且值跟子组件的ref一定要一直,不然没用的 -->
<ContentFrom
:formDataList="formDataList"
:formParams="formParams"
:formConfig="formConfig"
:formType="formType"
:ref="formConfig.ref"
>
<template slot="operation">
<el-button type="warning" @click="commitData">提交</el-button>
<el-button type="primary" @click="resetInfo">重置</el-button>
</template>
</ContentFrom>
</div>
</template>
<script>
import ContentFromfrom "@/components/ContentFrom.vue";
export default {
name: "content",
components: {
ContentFrom
},
data() {
return {
formParams: {
address: "",
level: ""
},
formDataList: [
{
label: "地区",
prop: "address",
type: "input",
placeholder: "请输入地区",
rules: [{ required: true }],
},
{
label: "水平",
prop: "level",
placeholder: "请输入水平",
type: "input",
}
],
formConfig: {
labelWidth: "100px",
inline: true,
ref: "formRef",
labelPosition: "right",
}
};
},
methods: {
resetInfo() {
this.formParams = {};
},
commitData() {
// 这样就可以获取子组件中的表单数据啦
this.$refs[this.formConfig.ref].transferData().then((date) => {
console.log(date);
});
},
},
};
</script>
其实在封装的时候想让这个表单可以运用到多个场景中(就类似常规的表单收集,搜索框之类的。呃……后面确实也是实现了(就是在每次应用的时候传递一个固定的变量去判断给一个不同的样式,差不多就可以实现想要的效果),但是最后的结果有点小崩,就是感觉表单一整个封装就在使用的时候很不友好。其实是有点纠结表单到底是统一封装好一点还是分开封装好一点(不封装的话,没什么比较独特的地方😅)
真希望有个大佬可以带带我这个菜鸡[向往.jpg]……