小程序app封装公用顶部筛选区uv-drop-down

参考ui:DropDown 下拉筛选 | 我的资料管理-uv-ui 是全面兼容vue3+2、nvue、app、h5、小程序等多端的uni-app生态框架

样式示例:

封装公用文件代码 dropDownTemplete

html 复制代码
<template>
	<!-- 顶部下拉筛选区封装公用组件 -->
	<view>
		<uv-drop-down ref="dropDown" sign="dropDown_1" :defaultValue="defaultValue" @click="selectMenu">
			<uv-drop-down-item v-for="(item,index) in uvDropDownItem" :name="item.name" type="2"
				:label="dropItem(item.name,index).label" :value="dropItem(item.name,index).value">
			</uv-drop-down-item>
			<uv-drop-down-item name="more" type="1" label='更多' extra-icon='empty-search' :value="0">
			</uv-drop-down-item>
		</uv-drop-down>
		<uv-drop-down-popup sign="dropDown_1" :click-overlay-on-close="true" :currentDropItem="currentDropItem"
			@clickItem="clickItem"></uv-drop-down-popup>
		<!-- 更多搜索 -->
		<view class="popupPosition">
			<uv-popup ref="popup" :safeAreaInsetTop="true">
				<view class="content">
					<view style="padding: 20rpx;">
						<uv-form labelPosition="left" :model="filterSheetData" ref="form">
							<uv-form-item v-for="(item,index) in formItem" :label="item.label" :prop="item.vModel"
								labelWidth="120" borderBottom width="150rpx" @click="handleItemClick(item)">
								<uv-input v-model="filterSheetData[item.vModel]" disabled disabledColor="#ffffff"
									:placeholder="item.placeholder" border="none"></uv-input>
								<uv-icon v-if="item.selectIcon" name="arrow-right"
									style="float: right;margin-right: 20rpx;"></uv-icon>
							</uv-form-item>

							<uv-button type="primary" text="搜索" customStyle="margin-top: 10px"
								@click="searchSheet"></uv-button>
							<uv-button type="error" text="重置" customStyle="margin-top: 10px"
								@click="resetSearchSheet"></uv-button>
						</uv-form>
					</view>
				</view>
			</uv-popup>
			<uv-popup ref="calendarsPopup" mode="bottom">
				<view class="calendarPopupStyle">
					<view class="cancel" @click="calendarsCancel">
						取消
					</view>
					<view class="confirm" @click="calendarsConfirm">
						确定
					</view>
				</view>
				<uv-calendars ref="calendars" insert mode="range" @confirm="(e)=>timeConfirm(e,calendarsType)"
					@change="(e)=>timeConfirm(e,calendarsType)" />
			</uv-popup>
			<uv-picker v-if="pickerShow" ref="picker" :columns="pickerColumns" keyName="label"
				@confirm="(e)=>pickerConfirm(e,pickerType)" @close="pickerClose"></uv-picker>
			<uv-input v-if="pickerInputShow" placeholder="请输入筛选内容" border="surround" clearable v-model="pickerValue"
				@change="pickerSearchChange" @clear="pickerSearchClear" :customStyle="pickerIptStyle"></uv-input>
		</view>
	</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				// 表示value等于这些值,就属于默认值
				defaultValue: [0, 'all', '0'],
				result: [],
				activeName: '',
				pickerType: "",
				pickerShow: false,
				pickerInputShow: false,
				pickerIptStyle: {
					position: 'fixed',
					bottom: '220px',
					transform: 'translate(-50%)',
					zIndex: 997
				},
				pickerColumns: [
					[{
						label: '数据加载失败',
						id: 0
					}]
				],
				queryParams: {
					json: {
						conditions: [],
						formId: '',
						orderBys: [],
					}
				},
				pickerValue: ''
			}
		},
		props: {
			// 下拉选项数据
			uvDropDownItem: {
				type: Array,
				default: () => ([])
			},
			// 更多下拉选中表单数据
			filterSheetData: {
				type: Object,
				default: () => ({})
			},
			filternetworkData: {
				type: Object,
				default: () => ({})
			},
			filterinitialData: {
				type: Object,
				default: () => ({})
			},
			// 表单项字段
			formItem: {
				type: Array,
				default: () => ([])
			},
			// 更多筛选中下拉数据列表
			olumnscData: {
				type: Array,
				default: () => ([])
			},
		},
		computed: {
			dropItem(name, index) {
				return (name, index) => {
					const result = {};
					const find = this.result.find(item => item.name === name);
					if (find) {
						result.label = find.label;
						result.value = find.value;
					} else {
						result.label = this.uvDropDownItem[index][name].label;
						result.value = this.uvDropDownItem[index][name].value;
					}
					return result;
				}
			},
			// 获取当前下拉筛选项
			currentDropItem() {
				let data = this.uvDropDownItem.find(item => item.name === this.activeName)
				// console.log(data&&data.name);//拿到name字段
				// console.log(data&&data[data.name]);//获取name字段中的数组
				return data && data[data.name]
			}
		},
		created() {},
		methods: {
			// 更多筛选中表单点击事件
			handleItemClick(item) {
				if (item.selectIcon) {
					if (item.type === 'text') {
						this.chooseSearchSelect(item.vModel);
					} else if (item.type === 'time') {
						this.chooseSearchTime(item.vModel);
					}
				}
			},
			// 选择内容(下拉选)
			chooseSearchSelect(type) {
				this.pickerType = type
				this.pickerColumnsAssignment()
				this.pickerShow = true
				this.$nextTick(() => {
					this.$refs.picker.open();
				})
				setTimeout(() => {
					this.pickerIptStyle['left'] = window.innerWidth / 2 + 'px'
					this.pickerInputShow = true
				}, 300)
			},
			pickerColumnsAssignment() {
				this.olumnscData.forEach(item => {
					if (item.name == this.pickerType) {
						this.$set(this.pickerColumns, 0, item.list)
					}
				})
			},
			// 快速过滤选择项
			pickerSearchChange(e) {
				if (e === '') {
					this.pickerColumnsAssignment()
				} else {
					this.olumnscData.forEach(item => {
						if (item.name == this.pickerType) {
							this.$set(this.pickerColumns, 0, item.list.filter((item) => item.label.includes(e)))
						}
					})
				}
			},
			// 快速过滤选择项清除
			pickerSearchClear() {
				this.pickerColumnsAssignment()
			},
			// 选择项确定
			pickerConfirm(e, type) {
				this.filternetworkData[type] = e.value[0]
				this.filterSheetData[type] = e.value[0].label
			},
			// 选择项取消
			pickerClose() {
				this.pickerShow = false
				this.pickerInputShow = false
			},
			// 选择时间
			chooseSearchTime(type) {
				this.calendarsType = type
				this.$refs.calendarsPopup.open();
			},
			// 选择时间取消
			calendarsCancel() {
				this.filternetworkData[this.calendarsType] = ""
				this.filterSheetData[this.calendarsType] = ""
				this.$refs.calendarsPopup.close();
			},
			// 选择时间确定
			calendarsConfirm() {
				this.$refs.calendarsPopup.close();
			},
			timeConfirm(e, type) {
				this.filternetworkData[type] = e.range
				this.filterSheetData[type] = e.range.before + ' / ' + e.range.after
			},
			//更多--搜索
			searchSheet() {
				this.queryParams.json.conditions = []
				this.formItem.forEach(item => {
					// 判断查询表单项是否有值
					if (this.filternetworkData[item.vModel]&&item.type=='text') {
						// 如果value有值说明是对象格式  将value值传递
						if (this.filternetworkData[item.vModel].value) {
							this.queryParams.json.conditions.push({
								field: item.vModel,
								operation: "like",
								value: this.filternetworkData[item.vModel].value
							})
							// 如果只是字段有值 说明是文本框
						} else {
							this.queryParams.json.conditions.push({
								field: item.vModel,
								operation: "like",
								value: this.filternetworkData[item.vModel]
							})
						}
					}
					if (this.filternetworkData[item.vModel]&&item.type=='time') {
						this.queryParams.json.conditions.push({
							field: item.vModel,
							operation: "<>",
							value: this.filternetworkData[item.vModel].before,
							value2: this.filternetworkData[item.vModel].after
						})
					}
				})
				this.$refs.popup.close()
				// 将查询条件传递给父组件
				this.$emit('searchSheet', this.queryParams.json)
			},
			resetSearchSheet() {
				this.$emit('resetSearchSheet')
				this.queryParams.json.conditions = []
				this.$refs.popup.close()
			},
			/**
			 * 点击每个筛选项回调
			 * @param {Object} e { name, active, type } = e
			 */
			selectMenu(e) {
				const {
					name,
					active,
					type
				} = e;
				this.activeName = name;
				// type 等于1 的需要特殊处理:type不等于1可以忽略
				if (type == 1) {
					this.$refs.popup.open('top');
				} else {
					// 找到 name 属性等于 this.activeName 的对象
					const dropDownItem = this.uvDropDownItem.find(item => item.name === this.activeName);
					if (dropDownItem) {
						const find = this.result.find(item => item.name == this.activeName);
						if (find) {
							const findIndex = dropDownItem.child.findIndex(item => item.label == find.label && item
								.value == find.value);
							dropDownItem.activeIndex = findIndex;
						} else {
							dropDownItem.activeIndex = 0;
						}
					}
				}
			},
			/**
			 * 点击菜单回调处理
			 * @param {Object} item 选中项 { label,value } = e
			 */
			clickItem(e) {
				// 下面有重新赋值,所以用let
				let {
					label,
					value
				} = e;
				const findIndex = this.result.findIndex(item => item.name == this.activeName);
				if (this.defaultValue.indexOf(value) > -1 && this[this.activeName].label) {
					label = this[this.activeName].label;
				}
				// 已经存在筛选项
				if (findIndex > -1) {
					this.$set(this.result, findIndex, {
						name: this.activeName,
						label,
						value
					})
				} else {
					this.result.push({
						name: this.activeName,
						label,
						value
					});
				}
				this.result = this.result.filter(item => this.defaultValue.indexOf(item.value) == -1);
				this.result.forEach(item => {
					if (item.name) {
						if (item.label == '全部') {
							if (this.queryParams.json.conditions.length) {
								this.queryParams.json.conditions.forEach((itens,indexs)=>{
									if(itens.field === item.name){
									this.queryParams.json.conditions.splice(indexs,1)
									}
								})	
							}
						} else {
							// 添加筛选参数
							if (this.queryParams.json.conditions.length) {
								this.queryParams.json.conditions.forEach((itens,indexs)=>{
									if(itens.field === item.name){
									this.queryParams.json.conditions.splice(indexs,1)
									}
								})
								this.queryParams.json.conditions.push({
									field: item.name,
									operation: "=",
									value: item.value
								})
								
							} else {
								this.queryParams.json.conditions.push({
									field: item.name,
									operation: "=",
									value: item.value
								})
							}
						}
					}
				})
// 将查询条件传递给父组件
				this.$emit('searchSheet', this.queryParams.json)
			},
		}
	}
</script>

<style lang="scss" scoped>
	// 下拉选项滚动区域
	::v-deep .uv-dp__container {
		height: 400rpx !important;
		overflow-y: auto;
	}

	uni-view[data-v-4cc3c370] {
		top: 0 !important;
	}

	.calendarPopupStyle {
		display: flex;
		justify-content: space-between;
		border-bottom: 1rpx solid #ccc;

		>view {
			font-size: 34rpx;
			color: #909399;
			padding: 20rpx 20rpx;
		}
	}
</style>

父组件调用:

html 复制代码
<view class="header-fixed">
			<dropDownTemplete :uvDropDownItem="uvDropDownItem" :filterSheetData="filterSheetData" :filternetworkData="filternetworkData" 
			:filterinitialData="filterinitialData" :formItem="formItem" :olumnscData="olumnscData" @searchSheet="searchSheet" @resetSearchSheet="resetSearchSheet"></dropDownTemplete>
		</view>

data数据:

html 复制代码
// 下拉选项数据
				uvDropDownItem: [{
						name: 'brand',
						brand: {
							label: '品牌',
							value: 'all',
							activeIndex: 0,
							color: '#333',
							activeColor: '#2878ff',
							child: [{
								label: '全部',
								value: 'allto'
							}]
						},
					},
					{
						name: 'categoryId',
						categoryId: {
							label: '品类',
							value: 'all',
							activeIndex: 0,
							color: '#333',
							activeColor: '#2878ff',
							child: [{
								label: '全部',
								value: 'allto'
							}]
						}
					}
				],
				// 更多下拉选项数据
				formItem:[
					{
						label:'品类',
						vModel:'categoryId',
						type:'text',
						placeholder:'请选择品类',
						selectIcon:true
					},
					{
						label:'品牌',
						vModel:'brand',
						type:'text',
						placeholder:'请选择品牌',
						selectIcon:true
					},
					{
						label:'更新时间',
						vModel:'updateTime',
						type:'time',
						placeholder:'请选择更新时间',
						selectIcon:true
					},
					{
						label:'创建时间',
						vModel:'createTime',
						type:'time',
						placeholder:'请选择创建时间',
						selectIcon:true
					}
				],
				filterSheetData: {
					categoryId: "",
					brand: "",
					updateTime: "",
					createTime: ""
				},
				filternetworkData: {
					categoryId: "",
					brand: "",
					updateTime: "",
					createTime: ""
				},
				filterinitialData: {
					categoryId: "",
					brand: "",
					updateTime: "",
					createTime: ""
				},
				olumnscData:[
					{
						name:'categoryId',
						list:[
						{label:'1',vaule:'fff'},
						{label:'2',vaule:'dfvdgf'}
					],
					},
					{
						name:'brand',
						list:[
						{label:'里奈',vaule:'里奈'},
						{label:'舞曲',vaule:'舞曲'}
					],
					}
				]

搜索和清除事件:

html 复制代码
// 更多-搜索
			searchSheet(data){
				console.log(data);
				//这里可进行搜索操作
			},
			// 更多-清除
			resetSearchSheet(){
				// 清空数据
				this.filterSheetData = this.filterinitialData
				this.filternetworkData = {
					categoryId: {label:'',value:''},
					brand: {label:'',value:''},
					updateTime: "",
					createTime: ""
				}
			},

最终样式图示例:

相关推荐
崔庆才丨静觅9 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606110 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅10 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅11 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment11 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅11 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊11 小时前
jwt介绍
前端
爱敲代码的小鱼11 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax