uniapp实用篇 | 产品要你做个移动端Web版本需求的下拉筛选菜单

919 阅读2分钟

碰到一个产品需求,当你抽屉组件和picker组件都使用不了,需要一个横排的下拉菜单没办法直接手写

正文直接开始....

⭐效果图:

demo.png

本文基于uniapp的vue3举一个demo做例子

 M记的全部下拉展开是汉堡、薯条、奶茶
 螺蛳粉店全部下拉是螺蛳粉

demo1.png

demo2.png

1. 数据初始化:

父组件:

	const initSelect = [        {                name: '全部',                children: [{                                name: '汉堡',                                topId:0                        },                        {                                name: '薯条',                                topId:0                        },                        {                                name: '奶茶',                                topId:0                        },                        {                                name: '螺蛳粉',                                topId:1                        }                ]
        },
        {
                name: '价格',
                children: [{
                                name: '价格升序'
                        },
                        {
                                name: '价格降序'
                        },
                ]
        },
        {
                name: '我的挂售',

        },
        {
                name: '立即挂售',

        }
]

子组件:

    interface Props {
        heads : Array < any > ,//分类排序参数
        categoryStyle ? : Object,//分类自定义样式
        SelectColor ? : string,//选中颜色样式
        defaultColor ? : string,//默认颜色样式
        TextSize ? : string,//字体大小
        iconSize ? : number//上下箭头大小
    }
    const prop = withDefaults(defineProps < Props > (), {
        heads: () => {
                return []
        },
        categoryStyle: () => ({

        }),
        SelectColor: '#6D59E4',
        defaultColor: '#979797',
        TextSize: '24rpx',
        iconSize: 9

    })

子组件根据topId进行判断是否显示该数据

2.子组件选择一级菜单:

弹出的下拉框样式以及遮罩样式:

下拉框整体样式添加z-index:1007

template加一个view遮罩:

<view :style="currentShow?mask:''"></view>

// 遮罩样式
const mask = {
	height: '100vh',
	backgroundColor: 'rgba(0, 0, 0, 0.4)',
	position: 'fixed',
	zIndex: '999',
	width: '100%'
}

点击一级菜单触发点击事件:

 /**
 * @param {number} index 选择头部索引
 * @param {boolean} isParentCall 是否来自父组件的调用
 */
const selectIndex = (index:number,isParentCall?:boolean) => {
	currentIndex.value = index
	parentIndex.value = list.value[index].id
	let arr = []
	list.value[index].children.map((item,cur) => {
		let obj = {}
		// 判断是否需要额外控制二级菜单显示
		if(!isNaN(item.topId)){
			childChange.value.id == item.topId ? arr.push(item) : ''
		}else{
			arr.push(item)
		}
	})
	childList.list = arr
	if(arr.length !== 1 && !isParentCall){
		currentShow.value = true
	}else{
		childSelect(childList.list[0])
	}

}
    

通过点击不同的一级菜单调用selectIndex函数传当前的索引index,遍历当前list下的children判断是否有topId和是否跟父组件的childChange.id相等,得出符合的下拉框数据。

3.父组件更改头部tab切换对应的下拉框数据:

provide更改cateSortChange的数据,子组件inject接收并且使用watch监听他的改变。

父组件:

const cateSortChange:any = ref({id:0})

// 深层次传参
provide('changeHeadSelect',cateSortChange)

// 修改菜单事件
const changeHeader = (index:number) => {
	currentIndex.value = index
	cateSortChange.value = {...cateSortChange.value,id:index}
}

子组件监听:

watch(()=>childChange,(news:any,olds:any)=>{
// 监听父组件操作,修改对于显示的菜单
if(Object.values(news).length !== 0){
    news.value.currentIndex != undefined ? currentIndex.value = news.value.currentIndex : ''
    news.value.childIndex != undefined ? currentChildIndex.value = news.value.childIndex : ''
    selectIndex(currentIndex.value,true)
}
},{
deep:true
})

😄总结

本文的代码在DCloud插件市场发布,感兴趣可以搜索zzx-dropDown-menu下载下来使用或者观摩,欢迎指正。