1、业务需求:封装一个下拉框的组件,下拉框弹出时,下拉框下面有半透明遮罩,下拉框上面正常显示,效果如图:
2、问题:当一个页面同时引用多次该组件时,下拉框和遮罩会同时存在彼此叠加
3、解决:
其实这个过程就是一个兄弟组件之间的通信问题,当有下拉框打开时,通知另外的下拉框都保持关闭状态。
父页面引用组件代码:
<template>
<!-- 筛选框 -->
<view class="searchBox">
<view class="inline shopNum">商家总数<text class="blueText">{{shopCount}}</text></view>
<dropDown :drpoDownName="'智能排序'" :selectorScrollList="industryBrand"></dropDown>
<dropDown :drpoDownName="'时间筛选'" :selectorScrollList="time"></dropDown>
</view>
<!-- 筛选框结束 -->
</view>
</template>
<script>
import dropDown from '@/components/sm-org-dropDown/sm-org-dropDown'
export default {
data() {
return {
name: "orgShop",
}
},
components: {
dropDown
},
}
</script>
<style>
</style>
子组件代码:
<template>
<!-- 灰色下拉选择框 -->
<view class="dropDown">
<view class="drpoDownName" @click="showList">{{drpoDownName}} <text :class="selected?'cuIcon-triangledownfill':'cuIcon-triangleupfill'"></text></view>
<!-- 下拉可选列表 -->
<view class="drpoDownSelector" v-if="selected">
<scroll-view scroll-y="true" class="selectorScroll">
<view class="selectorScrollList" :class="checkedId == item.id ? 'selectorScrollListChecked' : ''" v-for="(item,index) in selectorScrollList" :key="item.id" @click="onSelectorClick(item.id)">
<text>{{item.value}}</text>
</view>
</scroll-view>
</view>
<!-- 遮罩层 -->
<view class="mask" v-if="selected" @click.stop="close"></view>
</view>
</template>
<script>
export default {
name: 'sm-org-dropDown',
props:{
drpoDownName:{
type:String,
default:''
},
selectorScrollList:{
type: Array,
default:[]
}
},
data() {
return {
selected:false,
checkedId:0,
//给子组件定义一个不会重复的gid,用来标识每一个子组件
gid:`sm-org-dropDown-${(new Date()).getTime()}${Math.random()}`
}
},
created() {
//在created的时候,给子组件放置一个监听,这个时候只是监听器被建立,此时这段代码不会生效
//uni.$on接收一个sm-org-dropDown-show的广播
uni.$on('sm-org-dropDown-show',(targetId)=>{
//接收广播,当该组件处于下拉框被打开的状态,并且跟下一个被点击的下拉框的gid不同时,将该组件的下拉框关闭,产生一个互斥效果。
if(this.selected && this.gid!=targetId){
this.selected=false
}
})
},
//当子组件销毁的时候,将建立的监听销毁,这里不会影响代码效果,但是在多次反复引用组件时,会在根节点定义越来越多的监听,长此以往影响性能,所以在不用的时候及时销毁,养成好习惯
beforeDestroy() {
uni.$off('sm-org-dropDown-show')
},
methods:{
showList(){
this.selected = !this.selected
//在下拉框被点击的时候发出一个广播,将被点击到的这个组件gid广播出去
if(this.selected){
uni.$emit('sm-org-dropDown-show',this.gid)
}
},
onSelectorClick(id){
// this.selected = false;
this.checkedId = id
},
close (){
this.selected = false
}
}
}
</script>
<style>
.mask{
width: 100%;
height: 100%;
position:absolute;
left:0;
/* top:0; */
background: rgba(0,0,0,0.5);
}
.dropDown{
display: inline-block;
}
.drpoDownName{
color: rgba(128, 128, 128, 1);
font-size: 11px;
}
.drpoDownSelector{
padding: 10px;
position: absolute;
left: 0;
width: 100%;
background-color: #FFFFFF;
z-index: 2;
}
.selectorScroll{
max-height: 200px;
}
.selectorScrollList{
line-height: 45px;
color: rgba(80, 80, 80, 1);
font-size: 14px;
}
.selectorScrollListChecked{
color: rgba(42, 130, 228, 1);
}
</style>

4849

被折叠的 条评论
为什么被折叠?



