移动端下拉筛选组件

uniapp + uview 下拉筛选

新建组件文件夹selectDownBox

<!-- classFilter.vue -->
<template>
	<view>
		<view v-for="(emi,e) in proList" :key="e">
			<view @click="showChildList(e)" :ref="'classBox' + e" class="drop-item" :style="{'color':isActive[e]? '#2979ff' : '#909399','padding-left': nodes * 25 + 'rpx'}">
				{{emi[emiName]}}
				<u-icon v-if="emi.children" :name="scopesDefault[e] ? 'arrow-down' : 'arrow-right'" size="15"
					:color="scopesDefault[e] ? '#2979ff' : '#909399'" class="ml-8">
				</u-icon>
				<u-icon v-if="isActive[e]" name="checkbox-mark" size="15" color="#2979ff" style="position: absolute;right: 50rpx;"></u-icon>
			</view>
			<u-line></u-line>
			<template v-if="emi.children">
				<class-filter v-on="$listeners" :nodes="nodes + 1" v-if="scopesDefault[e]" :proList="emi.children"
					:emiName="emiName" :dtitle="dtitle">
				</class-filter>
			</template>
		</view>
	</view>
</template>

<script>
	export default {
		name: 'classFilter',
		props: {
			proList: {
				type: Array,
				default () {
					return []
				}
			},
			emiName: {
				type: String,
				default: 'no'
			},
			dtitle: {
				type: String,
				default: 'no'
			},
			nodes:{
				type:Number,
				default:0
			}
		},
		data() {
			return {
				scopesDefault: [],
				scopes: [],
				isActive: []
			}
		},
		mounted() {
			this.init()
		},
		methods: {
			init() {
				this.proList.forEach((item, index) => {
					this.scopesDefault[index] = false;
					this.$set(this.isActive, index, item[this.emiName] === this.dtitle)
					if (item.children) {
						this.scopes[index] = true;
					} else {
						this.scopes[index] = false;
					}
				})
			},
			showChildList(e) {
				if (this.scopes[e]) {
					if (this.scopesDefault[e]) {
						this.$set(this.scopesDefault, e, false);
					} else {
						this.scopesDefault.map((item, index) => {
							this.$set(this.scopesDefault, index, index === e)
						})
					}
				} else {
					this.$set(this.isActive, e, true)
					this.$emit('getClass', this.proList[e])
				}
			}

		}
	}
</script>

<style scoped lang="scss">

</style>

<!-- sekectDown.vue -->
<template>
	<view class="position-relative w-100">
		<view class="w-100 d-flex a-center class-btn">
			<u-button class="flex-1" v-for="(menu,m) in refMenu" :key="m" :text='menu.dTitle'
				:type="menu.active ? 'primary' : 'info'" :plain="true" :size="btnSize" shape='circle'
				:icon="showDrop && menu.active ? 'arrow-down-fill' : 'arrow-up-fill'" @click="menuOpen(m)"></u-button>
		</view>
		<u-overlay :show="showDrop" style="top: 200rpx;" :style="[popupStyle]">
			<block v-if="!$slots.default && !$slots.$default">
				<view class="w-100 bg-white">
					<template v-if="refMenu[current] && refMenu[current][keyPro]">
						<scroll-view scroll-y style="max-height: 60vh;">
							<class-filter :ref="'class'+refMenu[current][keyPro]" :dtitle='refMenu[current].dTitle'
								:proList="refMenu[current][listName]" emiName="classificationName"
								@getClass="textClass"></class-filter>
						</scroll-view>
					</template>
				</view>
			</block>
			<slot v-else></slot>
		</u-overlay>
	</view>
</template>

<script>
	import classFilter from '@/components/selectDown/classFilter.vue'
	export default {
		props: {
			title: {
				type: String,
				default: 'title'
			},
			menuList: {
				type: Array,
				default () {
					return []
				}
			},
			listName: {
				type: String,
				default: undefined
			},
			btnSize: {
				type: String,
				default: 'small'
			},
			proper: {
				type: String,
				default: 'proper'
			},
			duration: {
				type: Number,
				default: 300
			},
			keyPro: {
				type: String,
				default: 'keyPro'
			}
		},
		components: {
			classFilter
		},
		computed: {
			popupStyle() {
				let style = {};
				style['transition-duration'] = this.duration / 1000 + 's';
				return style;
			}
		},
		data() {
			return {
				isChose: false,
				showDrop: false,
				current: 9999,
				liList: [],
				refMenu: []
			}
		},
		mounted() {
			this.refMenu = JSON.parse(JSON.stringify(this.menuList))
			this.refMenu.map(item => {
				this.$set(item, 'dTitle', item[this.title])
				this.$set(item, 'active', false)
			})
		},
		methods: {
			menuOpen(m) {
				if (m === this.current && this.showDrop) {
					this.showDrop = false
				} else {
					this.showDrop = true
					this.refMenu.map((item, index) => {
						this.$set(item, 'active', index === m)
					})
					this.current = m
					this.liList = this.menuList[m][this.listName]
				}
			},
			closeDrop(ob) {
				setTimeout(() => {
					this.showDrop = false
					this.$emit('menuClick', ob)
				}, this.duration)
			},
			textClass(da) {
				console.log('textClass(da)', da)
				this.refMenu[this.current].dTitle = da.classificationName
				this.refMenu[this.current].active = false
				let ob = {
					keyPro: this.refMenu[this.current][this.keyPro],
					value: da.id
				}
				this.closeDrop(ob)
			}
		}
	}
</script>

<style scoped lang="scss">
	.class-btn{
		::v-deep .u-icon--right {
			position: absolute;
			right: 20rpx;
		}
		::v-deep .u-button__text{
			line-height: 1;
			text-overflow: ellipsis;
			white-space: nowrap;
			overflow: hidden;
			width: 75%;
		}
	}
</style>

 使用

<select-down-box ref="selectBox" :menuList="droList" listName="selectList" keyPro="type" title="name" proper="label" @menuClick="chDrownItem"></select-down-box>

import selectDownBox from '@/components/selectDown/selectDown.vue'
const droList = [
                  {
					name: '分类1',
					type: 'tj',
					selectList: [{
							children: null,
							id: "1111111",
							classificationName: "子分类"
						},
						{
							children: null,
							id: "1111111",
							classificationName: '子分类'
						},
						{
							children: null,
							id: "1111111",
							classificationName: '子分类'
						}
					]
				},
                {
					name: '分类2',
					type: 'tj2',
					selectList: [{
							children: [{children: null,classificationName: "子分类测试嘎嘎22",classificationSort: "3"}],
							id: "1111111",
							classificationName: "子分类"
						}
					]
				}
              ]
const chDrownItem = function(da) { console.log(da) }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值