likes
comments
collection
share

基于vue3+elementPlus封装通用查询表单

作者站长头像
站长
· 阅读数 6

在这个大神如牛的时代里,AI都能帮你写代码的时代里,查询表单封装也不是什么牛逼的技术,只是基于总结记录下来,希望在前端的路上留个脚印吧。 废话不多说,上正题。

一、思路

  1. 定义一个组件,里面定义通用的表单组件,如:input输入框、select下拉框、datepicker日期选择控件、select+input复合、cascader+input复合。
  2. 组件里针对传入的配置config进行初始化值回显到表单中
  3. placeholder的默认值处理
  4. 日期控件的格式处理
  5. 监听config的变化
  6. 将查询回调和重置回调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
    })
}

四、效果图

基于vue3+elementPlus封装通用查询表单

转载自:https://juejin.cn/post/7360917303087349814
评论
请登录