碰到一个产品需求,当你抽屉组件和picker组件都使用不了,需要一个横排的下拉菜单没办法直接手写
正文直接开始....
⭐效果图:
本文基于uniapp的vue3举一个demo做例子
M记的全部下拉展开是汉堡、薯条、奶茶
螺蛳粉店全部下拉是螺蛳粉
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
})