小程序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: ""
				}
			},

最终样式图示例:

相关推荐
潜意识起点19 分钟前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛24 分钟前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode
IT女孩儿34 分钟前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
m0_748256563 小时前
如何解决前端发送数据到后端为空的问题
前端
请叫我飞哥@3 小时前
HTML5适配手机
前端·html·html5
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js
F-2H6 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
苹果酱05676 小时前
「Mysql优化大师一」mysql服务性能剖析工具
java·vue.js·spring boot·mysql·课程设计
gqkmiss7 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件
m0_748247559 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php