组件名:uv-drop-down

点击下载&安装 (opens new window)

该组件主要提供筛选下拉筛选框,内置基础筛选功能,可以根据自己的需求自定义筛选项。

兼容app-nvue,需要内置三个组件进行配合使用,uv-drop-down属于菜单项(其实还包括子组件uv-drop-down-item),uv-drop-down-popup属于筛选框。

只需要做简单的约定式配置,即可使用该功能,兼容性良好,已经在多端进行了多次测试。

# 平台兼容性

App(vue) App(nvue) H5 小程序 VUE2 VUE3

# 基本用法

该用法只提供选择项及配置的方式和下拉框盒子,内容需要自己定义。

# uv-drop-down

  • 设置 sign 属性,保证组件唯一性,如果一个项目用到多个该组件,就需要将每个 sign 设置不同,组件内部使用了uni.$on监听,不设置可能会互相影响。uv-drop-downuv-drop-down-popup组件都需设置且值必须相等。
  • 设置 defaultValue 属性,默认值,如下设置[0,'0','all'],如果value等于0或'0'即代表该选项还未进行选择,即不是选中状态。

# uv-drop-down-item

  • 设置 name 属性,选择项的字段标识,在处理逻辑的时候会用到。
  • 设置 label 属性,展示选中或未选中的文本。
  • 设置 value 属性,该项的值,如果不是defaultValue中的值,即是选中状态。
  • 设置 type 属性,1 - 没有筛选项,表示是否选中,2 - 有多个筛选项。
<template>
	<view style="height: 1000px;">
		<uv-drop-down
			ref="dropDown"
			sign="dropDown_1" 
			:defaultValue="[0,'0','all']" 
		>
			<uv-drop-down-item 
				name="order" 
				type="2" 
				label="综合排序" 
				value="all">
			</uv-drop-down-item>
			<uv-drop-down-item 
				name="type" 
				type="2" 
				label="文档格式" 
				value="0">
			</uv-drop-down-item>
			<uv-drop-down-item 
				name="vip_type" 
				type="1" 
				label='VIP文档'
				:value="0">
			</uv-drop-down-item>
		</uv-drop-down>
		<uv-drop-down-popup
			sign="dropDown_1"
			@popupChange="change"
		>
			<view style="width: 750rpx;height: 300rpx;background-color: #fff;"></view>
		</uv-drop-down-popup>
	</view>
</template>
<script>
	export default {
		onPageScroll() {
			// 滚动后及时更新位置
			this.$refs.dropDown.init();
		},
		methods: {
			change(e){
				console.log('弹窗打开状态:',e);
			}
		}
	}
</script>

# 完整示例

使用内置筛选项,就需要根据约定参数,格式可以直接使用如下示例,每个参数的作用会在下方说明:

<template>
	<view>
		<uv-drop-down 
			ref="dropDown"
			sign="dropDown_1" 
			text-active-color="#3c9cff"
			:extra-icon="{name:'arrow-down-fill',color:'#666',size:'26rpx'}" 
			:extra-active-icon="{name:'arrow-up-fill',color:'#3c9cff',size:'26rpx'}"
			:defaultValue="defaultValue" 
			:custom-style="{padding: '0 30rpx'}" 
			@click="selectMenu"
		>
			<uv-drop-down-item 
				name="order" 
				type="2" 
				:label="dropItem('order').label" 
				:value="dropItem('order').value">
			</uv-drop-down-item>
			<uv-drop-down-item 
				name="type" 
				type="2" 
				:label="dropItem('type').label" 
				:value="dropItem('type').value">
			</uv-drop-down-item>
			<uv-drop-down-item 
				name="vip_type" 
				type="1" label='VIP文档' 
				:value="dropItem('vip_type').value">
			</uv-drop-down-item>
		</uv-drop-down>
		<uv-drop-down-popup 
			sign="dropDown_1" 
			:click-overlay-on-close="true"
			:currentDropItem="currentDropItem" 
			@clickItem="clickItem"
			@popupChange="change"
		></uv-drop-down-popup>
	</view>
</template>
<script>
	export default {
		onPageScroll() {
			// 滚动后及时更新位置
			this.$refs.dropDown.init();
		},
		computed: {
			dropItem(name) {
				return (name) => {
					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[name].label;
						result.value = this[name].value;
					}
					return result;
				}
			},
			// 获取当前下拉筛选项
			currentDropItem() {
				return this[this.activeName];
			}
		},
		data() {
			return {
				// 表示value等于这些值,就属于默认值
				defaultValue: [0, 'all', '0'],
				// 筛选结果
				result: [{ name: 'order', label: '最新发布', value: 'new' }],
				// { name: 'order', label: '最新发布', value: 'new' }
				activeName: 'order',
				order: {
					label: '综合排序',
					value: 'all',
					activeIndex: 0,
					color: '#333',
					activeColor: '#2878ff',
					child: [{
						label: '综合排序',
						value: 'all'
					}, {
						label: '最新发布',
						value: 'new'
					}, {
						label: '低价优先',
						value: 'money'
					}]
				},
				type: {
					label: '文档格式',
					value: 'all',
					activeIndex: 0,
					color: '#333',
					activeColor: '#2878ff',
					child: [{
						label: '全部',
						value: 'all'
					}, {
						label: 'PDF',
						value: 'pdf'
					}, {
						label: 'WROD',
						value: 'word'
					}, {
						label: 'PPT',
						value: 'ppt'
					}]
				},
				vip_type: {
					label: 'VIP文档',
					value: 0,
					activeIndex: 0
				}
			}
		},
		methods: {
			change(e) {
				console.log('弹窗打开状态:',e);
			},
			/**
			 * 点击每个筛选项回调
			 * @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.clickItem({
						name: 'vip_type',
						label: 'VIP文档',
						value: e.active ? 1 : 0
					});
				} else {
					const find = this.result.find(item => item.name == this.activeName);
					if (find) {
						const findIndex = this[this.activeName].child.findIndex(item => item.label == find.label && item.value == find.value);
						this[this.activeName].activeIndex = findIndex;
					} else {
						this[this.activeName].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);
				uni.showModal({
					content: `筛选的值:${JSON.stringify(this.result)}`
				})
			}
		}
	}
</script>

# 完整示例

# API


参数 类型 默认值 说明
sign String | Number UVDROPDOWN 组件唯一标识,需要手动传
default-value Array [0,'0','all'] 默认值,表示参数value属于这里面的值,就说明是未选中即是默认展示的值。eg:上面示例中的{label: '全部',value: 'all'} 即是默认值。后续处理逻辑也可以根据是否是其中值进行过滤。
is-sticky Boolean true 是否吸顶
text-size String 30rpx 每项字体大小
text-color String #333 每项文本颜色
text-active-size String 30rpx 每项选中状态字体大小
text-active-color String #3c9cff 每项选中状态文本颜色
extra-icon Object {name: 'arrow-down', size: '30rpx', color: '#333'} 每项右侧图标,暂时只支持设置默认值中的3个参数,参考 uv-icon (opens new window)
extra-active-icon Object {name: 'arrow-up', size: '30rpx', color: '#3c9cff'} 每项选中后右侧图标,暂时只支持设置默认值中的3个参数,参考 uv-icon (opens new window)
参数 类型 默认值 说明
name String | Number - 字段标识
type String | Number - 类型 1 没有筛选项,直接进行选中和不选中 2 有多个选项
label String - 筛选的文本
value String | Number | null - 筛选的值
is-drop Boolean false 该项是否打开,可用于重置选项状态
参数 类型 默认值 说明
sign String | Number UVDROPDOWN 组件唯一标识,需要手动传,与DropDown组件必须保持一致
z-index String | Number 999 弹出层的层级
opacity String | Number 0.5 遮罩层的透明度
click-overlay-on-close Boolean true 是否允许点击遮罩层关闭弹窗
current-drop-item Object - 当前下拉筛选菜单对象
key-name String label 指定从当前下拉筛选菜单对象元素中读取哪个属性作为文本展示
事件名 说明 返回参数
@selectMenu 点击每项菜单回调 { name, active, type } = e,active - 是否打开该项
事件名 说明 返回参数
@clickItem 点击筛选回调处理 { label, value } = e
@popupChange 打开关闭弹窗触发 { show }=e,true或false
名称 说明
init 初始化弹窗的位置,在滚动时可以调用此方法,及时更新位置
名称 说明
open 打开弹窗
close 关闭弹窗
名称 说明
default 默认插槽,完全自定义内容,包括逻辑都需自己写