vue3+Element Plus功能组件封装——条件搜索(输入框(可新增删除),下拉选择框,日期选择)

目录

1.html部分

2.js部分

3.使用

4.附加


后台管理做多了,会发现无非就是一些,表单和表格,没什么新东西,直接套模板即可,下次遇到直接用,别再重复造轮子了,多花点时间推升自己!

1.html部分

选择性使用,可根据v-if else区分

<el-form ref="fromRef"  style="display:flex;">
	<template style="display:flex;flex-wrap:wrap;">
		<el-form-item v-for="item in FormData.formItems" :label="item.label">
			<!-- 判断是输入框还是选择框 选择框给出 是否多选属性  (附加表单验证) -->
			<el-input v-if="item.type=='input'" v-model="item.inputValue" :placeholder="item.placeholder"
				@change="inputChange(item.key,$event)" />
			<el-select v-else v-model="item.selectValue" :disabled="item.disabled" :multiple="item.multiple"
				:collapse-tags="item.collapsetags" :placeholder="item.placeholder"
				@change="selectChange(item.key,$event)" style="width: 200px;">
				<el-option v-for="option in item.selectOptions" :key="option.value" :label="option.label"
					:value="option.value" />
			</el-select>
            <template v-else-if="item.type=='multipleInput'">
				<template v-for="(time,index) in item.inputValue" :key="index">
					<div class="" style="width: 100%;">
						<el-input v-model="item.inputValue[index]" style="margin:0 5px 10px 0"
							@change="multipleInputChange(item.key,item.inputValue)"
							:placeholder="item.placeholder" />
						<el-icon v-if="index==0" style="font-size:20px" @click="addInput(item.key)">
							<CirclePlus />
						</el-icon>
						<el-icon v-else style="font-size:20px" @click="delInput(item.key,index)">
							<Remove />
						</el-icon>
					</div>
			
				</template>
			</template>
		</el-form-item>
		<!-- 判断有没有时间 -->
		<el-form-item :label="$t('CMP.time')" v-if="FormData.isTimePicker">
			<date-time-picker ref="childRef" @selectedDate="getSelectedDate"
				:toclear="false"></date-time-picker>
		</el-form-item>
	</template>
</el-form>

2.js部分

接收父组件数据,渲染页面;将搜索条件数据通过emit方法返回给父组件

import dateTimePicker from '@/components/dateTimePicker.vue'

let props = defineProps({
	FormData: Object
})

const emit = defineEmits()

const selectChange = (key, value) => {
	emit('selectFromChange', {
		key,
		value
	})
	console.log(key, value);
}
const inputChange = (key, value) => {
	emit('inputChange', {
		key,
		value
	})
	console.log(key, value);
}
const getSelectedDate = (date) => {
	emit('dateChange', date)
	console.log(date);
}
//输入框的新增和删除
    const multipleInputChange = (key, inputValue) => {
		emit('multipleInputChange', {
			key,
			inputValue
		})
		console.log(key, inputValue);
	}
	
	const addInput = (key) => {
		emit('addInput', key)
	}
	
	const delInput = (key, index) => {
		emit('delInput', {
			key,
			index
		})
	}

3.使用

<template>
	<div class="common_style">
		<select-module 
            :FormData="formData"
            @inputChange="inputChange" 
            @selectFromChange="selectFromChange"
            @dateChange="dateChange"
            @addInput="addInput"
            @multipleInputChange="multipleInputChange" 
            @delInput="delInput">
        </select-module>
	</div>
</template>
<script setup>
	import selectModule from '@/components/selectModule.vue'
	
	const inputChange = (data) => {
		searchFormData[data.key] = data.value
	}
	
	const selectFromChange = (data) => {
		searchFormData[data.key] = data.value
	}

    // 增加一个日期时间
	const addInput = (key) => {
		formData.formItems.map(item => {
			if (item.key == key) {
				item.inputValue.push('')
			}
		})
	}

    const delInput = (data) => {
		formData.formItems.map((item) => {
			if (item.key == data.key) {
				item.inputValue.splice(data.index, 1)
				updateInfo[data.key] = item.inputValue
			}
		})
		updateInfo[data.key] = updateInfo[data.key].filter(item => item)
	}

    const multipleInputChange = (data) => {
		data.inputValue = data.inputValue.filter(item => item)
		updateInfo[data.key] = data.inputValue
	}
	
    let updateInfo = {}//用于接收子组件数据

	const formData = reactive({
		formItems: [{
				type: 'input',
				key: 'ID',
				inputValue: "",
				label: i18n.global.t('DQ.deviceID'),
				placeholder: i18n.global.t('DQ.pleaseInputID')
			},
			{
				type: 'select',
				key: 'Type',
				selectValue: "",
				label: i18n.global.t('DQ.Type'),
				multiple: true,
				collapsetags: true,
				placeholder: i18n.global.t('DQ.pleaseSelectType'),
				selectOptions
			},
            {
				type: 'multipleInput',
				key: 'phones',
				inputValue: [],
				label: i18n.global.t('DM.phoneNumbers'),
				placeholder: i18n.global.t('DM.phoneNumbersPlaceholder')
			},
		]
		isTimePicker: true
	})
</script>

其中,multiple: truecollapsetags: true用于选择框的多选配置

输入框可以选择性的增加或删减,应用场景可能是输入多个邮箱或者电话号码,通过加减号动态的控制输入框的数量,取值时通过filter函数去除重复部分

4.附加

上述时间日期选择组件为额外封装

可实现限制时间范围,时间格式转换,快速选择范围内时间

封装代码如下:

<template>
	<div class="">
		<el-date-picker style="color: #809AAB;" :shortcuts="shortcuts" v-model="curentTime" type="datetimerange"
			 :start-placeholder="$t('CMP.startTime')" 
			 :disabled-date="disabledDate" :end-placeholder="$t('CMP.endTime')" @change="sureDate" />
	</div>
</template>


<script setup>
	import {
		ref
	} from 'vue'
	const emit = defineEmits()
	let props = defineProps({
		defaultTimeValue: Array
	})
	//如果要设置默认时间使用 此处的v-model值
	const curentTime = ref(props.defaultTimeValue)


	const sureDate = (e) => {
		if (e) {
			console.log(formatDate(e[0]), formatDate(e[1]));
			curentTime.value = [formatDate(e[0]), formatDate(e[1])]
		} else {
			curentTime.value = []
		}
		//将选中的值传递给父组件
		emit('selectedDate', curentTime.value)
	}

	const clearDate = () => {
		curentTime.value = []
	}
	//获取前一个月的今天
	const getPrevMonthSameDay = (num) => {
		const now = new Date();
		const prevMonth = new Date(now.getFullYear(), now.getMonth() - num, 1);
		const daysInPrevMonth = new Date(prevMonth.getFullYear(), prevMonth.getMonth() + 1, 0).getDate();
		const sameDayInPrevMonth = Math.min(now.getDate(), daysInPrevMonth);
		return new Date(prevMonth.getFullYear(), prevMonth.getMonth(), sameDayInPrevMonth);
	};

	// 创建日期限制函数
	const disabledDate = (time) => {
		return time < getPrevMonthSameDay(2) || time > new Date();
	};

	const shortcuts = [{
			text: 'Last week',
			value: () => {
				const end = new Date()
				const start = new Date()
				start.setDate(start.getDate() - 7)
				return [start, end]
			},
		},
		{
			text: 'Last month',
			value: () => {
				const end = new Date()
				const start = new Date()
				start.setMonth(start.getMonth() - 1)
				return [start, end]
			},
		},
		{
			text: 'Last 3 months',
			value: () => {
				const end = new Date()
				const start = new Date()
				start.setMonth(start.getMonth() - 3)
				return [start, end]
			},
		},
	]
	
	//将标准时间格式转为类似于 202408051104 格式
	const formatDate = (date) => {
		var year = date.getFullYear();
		var month = ("0" + (date.getMonth() + 1)).slice(-2); // getMonth返回的是0-11,所以需要+1
		var day = ("0" + date.getDate()).slice(-2);
		var hours = ("0" + date.getHours()).slice(-2);
		var minutes = ("0" + date.getMinutes()).slice(-2);
		var seconds = ("0" + date.getSeconds()).slice(-2);
		return `${year}${month}${day}${hours}${minutes}${seconds}`;
	}

	defineExpose({
		clearDate
	})
</script>



<style scoped>
	:deep(.el-date-editor .el-range-input) {
		color: #fff;
	}
</style>

<think>好的,用户问的是如何在Vue3Element Plus中关闭el-select的下拉弹框。我需要先回忆一下Element Plus中el-select的相关API和事件。 首先,el-select组件有一个blur方法,可以使其失去焦点,从而关闭下拉框。但可能用户需要的是更直接的控制方式。比如在某个事件触发时关闭下拉框。 另外,el-select有一个visible属性,可以用.sync修饰符来双向绑定,控制下拉框的显示与隐藏。不过Vue3.sync已经被v-model:propName替代。所以可能需要使用v-model:visible来绑定一个变量,通过改变这个变量来控制弹框的关闭。 但需要确认Element Plus的el-select是否支持visible这个prop。查阅文档发现,el-select有一个disabled属性,如果设置为true,下拉框不会展开。但用户可能想要的是在特定条件下主动关闭已经展开的下拉框。 可能更好的方法是使用ref获取el-select实例,然后调用其blur方法。比如,给el-select设置ref="selectRef",然后在方法中调用this.$refs.selectRef.blur()。不过在Vue3中,组合式API的写法可能有所不同,需要使用ref来引用组件实例。 举个例子,在setup函数中,const selectRef = ref(null); 然后通过selectRef.value.blur()来触发关闭。需要注意组件暴露的方法是否正确。 还有一种情况是,当选择选项后希望自动关闭下拉框,这时候el-select默认会在选择后关闭,但如果有特殊情况需要手动触发,比如在@change事件中调用blur方法。 另外,可能涉及到点击外部关闭下拉框,这通常由Element Plus自动处理,但如果有自定义需求,可能需要监听事件或者修改相关配置。 总结起来,主要的解决方案有两种:一是使用v-model:visible绑定变量来控制显隐,二是通过ref调用blur方法。需要验证这两种方法在Element Plus中的可行性。 查阅Element Plus的官方文档,发现el-select有一个visible属性,可以通过v-model:visible绑定,当设置为false时可以关闭下拉框。同时,blur方法确实存在,用于让选择器失去焦点,从而关闭下拉框。 因此,回答用户时需要分情况说明这两种方法的具体使用步骤和代码示例。同时提醒用户注意Vue3的语法变化,比如使用ref和组合式API的写法。</think>在 Vue3 + Element Plus 中关闭 el-select 下拉弹框的两种常用方法: ```html <template> <!-- 方法1:通过 visible 属性控制 --> <el-select v-model="selectedValue" v-model:visible="isDropdownVisible" @visible-change="handleVisibleChange" > <el-option label="选项1" value="1" /> <el-option label="选项2" value="2" /> </el-select> <!-- 方法2:通过 ref 调用 blur 方法 --> <el-select ref="mySelect" v-model="selectedValue" @change="handleChange" > <el-option label="选项A" value="A" /> <el-option label="选项B" value="B" /> </el-select> </template> <script setup> import { ref } from &#39;vue&#39;; // 方法1相关代码 const isDropdownVisible = ref(false); const handleVisibleChange = (visible) => { // 可在此处添加关闭条件判断 if(visible) { // 需要自动关闭时可设置为 false // isDropdownVisible.value = false; } } // 方法2相关代码 const mySelect = ref(null); const handleChange = () => { mySelect.value.blur(); // 调用 blur 方法关闭弹框 } </script> ``` **两种方法对比:** 1. **v-model:visible 控制法** - 直接控制下拉框显隐状态 - 需要维护一个额外的响应式变量 - 适合需要精确控制展开/关闭时机的场景 2. **ref + blur() 方法** - 更接近原生操作方式 - 自动处理状态变化 - 适合在值变化后立即关闭的场景 **注意事项:** 1. Element Plus 2.3.8+ 版本支持 `visible` 属性 2. 使用组合式API时需确保正确使用 `ref` 引用 3. 避免在同一个操作中同时使用两种方法 4. 下拉框关闭时会自动触发 `blur` 事件 根据具体需求选择合适的方法,常规交互推荐使用第二种方法,需要复杂状态控制时建议使用第一种方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值