基于vue3+elementPlus封装通用查询表单
在这个大神如牛的时代里,AI都能帮你写代码的时代里,查询表单封装也不是什么牛逼的技术,只是基于总结记录下来,希望在前端的路上留个脚印吧。 废话不多说,上正题。
一、思路
- 定义一个组件,里面定义通用的表单组件,如:input输入框、select下拉框、datepicker日期选择控件、select+input复合、cascader+input复合。
- 组件里针对传入的配置config进行初始化值回显到表单中
- placeholder的默认值处理
- 日期控件的格式处理
- 监听config的变化
- 将查询回调和重置回调emit出去
二、查询表单组件代码
<template>
<div class="search-form-wrap">
<el-form ref="formRef" :model="form" onsubmit="return false">
<slot></slot>
<div class="search-form" v-for="item in formConfigList" :key="item.field">
<!-- input 输入框 -->
<div class="form-item" v-if="item.type === 'input'">
<el-form-item :label="item.label">
<el-input
v-model="form[item.field]"
:placeholder="item.placeholder || placeholderHandle(item)"
></el-input>
</el-form-item>
</div>
<!-- select 普通下拉框 -->
<div class="form-item" v-if="item.type === 'select'">
<el-form-item :label="item.label">
<el-select
v-model="form[item.field]"
clearable
:placeholder="item.placeholder || placeholderHandle(item)"
>
<slot name="customSelect">
<el-option
:label="obj.label"
:value="obj.value"
v-for="obj in item.options"
:key="obj.value"
></el-option>
</slot>
</el-select>
</el-form-item>
</div>
<!-- datePicker 日期范围选择 -->
<div class="form-item" v-if="item.type == 'datePicker'">
<el-form-item :label="item.label">
<el-date-picker
v-model="form[item.field]"
:type="item.pickType || 'daterange'"
range-separator="~"
:start-placeholder="placeholderHandle(item, 'start')"
:end-placeholder="placeholderHandle(item, 'end')"
@change="dateChange($event, item.field)"
:disabledDate="item.disabledDate || function dateFun() {}"
:format="item.format || 'YYYY-MM-DD'"
>
</el-date-picker>
</el-form-item>
</div>
<!-- complexInput 下拉框+输入框复合 -->
<div
class="form-item selectInput-item"
v-if="item.type == 'complexInput'"
>
<el-form-item :label="item.label">
<el-input
:placeholder="placeholderHandle(item, 'input')"
v-model="form[item.field[1]]"
>
<template #prepend>
<el-select
v-model="form[item.field[0]]"
:placeholder="placeholderHandle(item, 'select')"
@change="complexInputChange($event, item.options)"
>
<el-option
:label="obj.label"
:value="obj.value"
v-for="obj in item.options"
:key="obj.value"
></el-option>
</el-select>
</template>
</el-input>
</el-form-item>
</div>
<!-- cascaderInput 级联选择器+输入框复合 -->
<div class="form-item cascaderInput-item" v-if="item.type === 'cascaderInput'">
<el-form-item :label="item.label">
<el-input
:placeholder="placeholderHandle(item, 'input')"
v-model="form[item.field[1]]"
>
<template #prepend>
<el-cascader
:placeholder="placeholderHandle(item, 'select')"
v-model:value="form[item.field[0]]"
:options="item.options"
clearable
filterable
/>
</template>
</el-input>
</el-form-item>
</div>
<!-- cascaderInput 级联选择器 -->
<div class="form-item" v-if="item.type === 'cascader'">
<el-form-item :label="item.label">
<el-cascader
:placeholder="item.placeholder || placeholderHandle(item)"
v-model:value="form[item.field]"
:options="item.options"
clearable
filterable
/>
</el-form-item>
</div>
</div>
<slot name="right"></slot>
</el-form>
<div class="btns">
<el-button class="lv2-btn-blue" @click="searchHandle">
<i class="iconfont icon-sousuo"></i>
查询
</el-button>
<el-button class="lv2-btn-white" @click="resetHandle">
<i class="iconfont icon-zhongzhi"></i>
重置
</el-button>
</div>
</div>
</template>
<script setup>
import { reactive, toRefs, ref, onMounted, watch } from 'vue'
import moment from 'moment'
const props = defineProps({
formConfig: {
type: Object,
default: () => {}
}
})
const formConfigList = props.formConfig
const formRef = ref()
// 存储表单所有的值
const form = reactive({})
// 表单初始化
const formInit = (data) => {
data.forEach((item) => {
switch (item.type) {
case 'input':
case 'select':
case 'datePicker':
case 'cascader':
form[item.field] = item.default
break
case 'complexInput':
form[item.field[0]] = item.default.length > 0 ? item.default[0] : ''
form[item.field[1]] = item.default.length > 0 ? item.default[1] : ''
break
case 'cascaderInput':
form[item.field[0]] = item.default.length > 0 ? item.default[0] : []
form[item.field[1]] = item.default.length > 0 ? item.default[1] : ''
break
default:
}
})
formConfigList.value = data
}
onMounted(() => {
formInit(props.formConfig)
})
watch(()=> props.formConfig, (val) => {
formInit(val)
})
// 处理placeholder
const placeholderHandle = (data, flag) => {
switch (data.type) {
case 'input':
return data.placeholder || `请填写${data.label.replace(/:/, '')}`
case 'select':
return data.placeholder || `请选择${data.label.replace(/:/, '')}`
case 'datePicker': {
const placeholderArr = data.placeholder || ['开始日期', '结束日期']
return flag === 'start' ? placeholderArr[0] : placeholderArr[1]
}
case 'complexInput':
case 'cascaderInput': {
const placeholderArr = data.placeholder || ['请选择', '请填写关键字']
return flag === 'select' ? placeholderArr[0] : placeholderArr[1]
}
case 'cascader': {
return data.placeholder || `请选择${data.label.replace(/:/, '')}`
}
default:
return ''
}
}
// 日期选择器change事件
const dateChange = (data, fieldName) => {
if (data) {
let startTime = data[0]
let endTime = data[1]
// 格式化时间返回值
form[fieldName] = [
moment(startTime).format('YYYY-MM-DD'),
moment(endTime).format('YYYY-MM-DD')
]
}
}
const complexInputChange = (value, options = []) => {
options.forEach((item) => {
form[item.value] = undefined
})
}
const emit = defineEmits(['searchHandle','resetHandle'])
// 查询回调
const searchHandle = () => {
emit('searchHandle', form)
}
// 重置回调
const resetHandle = () => {
formInit(props.formConfig)
emit('resetHandle', form)
}
</script>
三、运用(片段代码)
<SearchForm :formConfig="formConfig" @searchHandle="searchHandle" @resetHandle="resetHandle" />
/**
{
type: 'input | select | datePicker | cascader | complexInput(下拉+输入框) | cascaderInput(级联 + 输入框)' // 表单类型,
field: 'name', //该表单项的字段名
label: '标签名', // 表单中文名
placeholder: '请填写报送人 | ['开始日期', '结束日期']' , // placeholder(可不传,不传自动生成:请填写xxxx)
default: '',// 默认值
}
complexInput、cascaderInput类型:
{
field: ['type', 'typeText'], // [下拉框字段名, 输入框字段名],
placeholder: ['请选择', '请填写关键字'], // 可不传 [下拉框placeholder, 输入框placeholder]
options: [
{
label:'',
value:'',
// 如果有children
children: [{
label:'',
value: ''
}]
}
]
}
*/
const formConfig = reactive([])
const carNumberOptions = computed(()=> {
return carNumberList.value.map(item => {
return {
// ...item,
label: item.numberplate,
value: item.id
}
})
})
async function getCarNumber() {
let {data:{data:{list}}} = await carListValid();
carNumberList.value= list
// 表单配置
formConfig.push({
type: 'select',
field: 'carId',
label: '车牌号:',
placeholder: '请车牌号', // 可不传,不传自动生成:请选择xxxx
default: '',
options: carNumberOptions.value
})
}
四、效果图
转载自:https://juejin.cn/post/7360917303087349814