uniapp drop-down box component

I wrote a small program before, and it is no problem to introduce a single drop-down box, but if a page introduces multiple drop-down box components, there will be bugs, such as the problem that multiple drop-down boxes can be expanded at the same time, which is fixed here. If you have any good way, please let me know~

Small program selection box_WeiflR10's blog-CSDN blog_Small program selection box

Subassembly

<template>
	<view style="position: relative;">
		<!-- 选中之后的数据展示 -->
		<view class="inputPlaceholder" v-if='inputVal' @click="changejiantou(num,allnum)">
			<input :placeholder="placeholderText" disabled v-model="inputVal"></input>
			<view class="jiantou1" v-if="evaluateCondition(`${'isjiantou' + this.num}`)"><i class="iconfont icon-jiantou1"></i></view>
			<view class="jiantou1" v-else><i class="iconfont icon-jiantou"></i></view>
		</view>
		<!-- 未选择时的Placeholder展示 -->
		<view class="inputPlaceholder" v-else @click="changejiantou(num,allnum)">
			<input :placeholder="placeholderText" disabled v-model="inputVal"></input>
			<view class="jiantou1" v-if="evaluateCondition(`${'isjiantou' + this.num}`)"><i class="iconfont icon-jiantou1"></i></view>
			<view class="jiantou1" v-else><i class="iconfont icon-jiantou"></i></view>
		</view>
		<!-- 下拉展开后的可选择内容 -->
		<view class="content" v-if="!evaluateCondition(`${'isjiantou' + this.num}`)">
			<view v-if="selectcontent.length==0" class="nodata">暂无数据</view>
			<view v-else :class="item.id==valueid ? 'active':'noactive'" v-for="(item,index) in selectcontent" @click="changecontent(item)">
				{
   
   {item.name}}
			</view>
		</view>
	</view>
</template>

<script>
import {mapState} from 'vuex'
export default{
    //selectcontent:下拉框的数据内容  num:本页面的第几个下拉框  allnum:本页面总共有多少个下拉框  placeholderText:placeholder显示的文字
	props:['selectcontent','num','allnum','placeholderText'],
	data() {
		return{
			inputVal:undefined,  //选中的值,name
			valueid:''  //选中的值,id
		}
	},
	computed:{
		// 箭头切换 false是展开,true是关闭
		...mapState({
			isjiantou0:state=>state.isjiantou0,
			isjiantou1:state=>state.isjiantou1,
			isjiantou2:state=>state.isjiantou2,
			isjiantou3:state=>state.isjiantou3,
			isjiantou4:state=>state.isjiantou4,
			isjiantou5:state=>state.isjiantou5,
			isjiantou6:state=>state.isjiantou6
		})
	},
    mounted(){
        for(var i=0;i<this.allnum;i++){
            this.$store.dispatch(`${'getjiantou' + i}`,true)
        }
    },
	methods: {
		// 箭头切换 false是展开,true是关闭
		evaluateCondition(condition) {   //condition:就是属性名isjiantou0,isjiantou1...
		    return this[condition]  //返回true或false
		},
		// 下拉框收起和下拉
		changejiantou(num,allnum){
			// 箭头切换 false是展开,true是关闭 将值存进vuex,改变时通知到所有相关组件
			if(this.$store.state[`${'isjiantou' + num}`]){
				this.$store.dispatch(`${'getjiantou' + num}`,false)
			}else{
				this.$store.dispatch(`${'getjiantou' + num}`,true)
			}
			for(var i=0;i<allnum;i++){
				if(i!=num){
					this.$store.dispatch(`${'getjiantou' + i}`,true)
				}
			}
		},
		// 选择数据后回显
		changecontent(e){
			this.$store.dispatch(`${'getjiantou' + this.num}`,true)
            //重复选同一个选择框,是不会触发事件的
			if(e.name!=this.inputVal){
				this.inputVal=e.name,
				this.valueid=e.id,
				this.$emit("change",e.id)  //change事件,可以在父组件中调用
			}
		},
	}
}
</script>

<style>
	.inputPlaceholder{
	    min-width: 360rpx;
        width: calc(100% - 60rpx);
	    height: 45rpx;
	    border: 1px solid #DEDEDE;
	    padding: 8rpx 40rpx 8rpx 20rpx;
	    margin-left: 16rpx;
	    border-radius: 10rpx;
	    position: relative;
	    overflow:hidden;
	    text-overflow: ellipsis;
	    white-space:nowrap;
	  }
	  .jiantou1{
	    position: absolute;
	    right: 10rpx;
	    top: 8rpx;
	    color: #CBCBCB;
	  }
	  .content{
	    min-width: 384rpx;
        width: calc(100% - 40rpx);
	    max-height: 240rpx;
	    position: absolute;
	    top: 62rpx;
	    left: 16rpx;
	    background: #FFFFFF;
	    box-shadow: 0px 0px 10px 1px rgba(209, 209, 209, 0.35);
		border-radius: 20rpx;
	    padding: 20rpx;
	    overflow-x: hidden;
	    overflow-y: scroll;
		z-index: 10000;
	  }
	  .noactive{
	    padding: 10rpx 0;
	  }
	  .active{
		padding: 10rpx 0;
	    color: #56D88A;
	  }
	  .nodata{
		  color: #999;
		  text-align: center;
	  }
</style>

parent component

<template>
	<view>
		<view class="input-row">
			<view class="input-title">类别</view>
			<ys-select :selectcontent='driverTypeOptions' placeholderText='请选择类别' num='0' :allnum='allnum'></ys-select>
		</view>
		<view class="input-row">
			<view class="input-title">人员</view>
			<ys-select :selectcontent='driverOptions' placeholderText='请选择人员' num='1' :allnum='allnum'></ys-select>
		</view>
		<view class="input-row">
			<view class="input-title">属性</view>
			<ys-select :selectcontent='carTypeOptions' placeholderText='请选择属性' num='2' :allnum='allnum'></ys-select>
		</view>
		<view class="input-row">
			<view class="input-title">车辆</view>
			<ys-select :selectcontent='carOptions' placeholderText='请选择车辆' num='3' :allnum='allnum'></ys-select>
		</view>
		<view class="input-row">
			<view style="padding-right: 20rpx;">运输人员</view>
			<ys-select :selectcontent='escortOptions' placeholderText='请选择运输人员' num='4' :allnum='allnum'></ys-select>
		</view>
		<view class="input-row">
			<view class="input-title">地点</view>
			<ys-select :selectcontent='recycleOptions' placeholderText='请选择地点' num='5' :allnum='allnum'></ys-select>
		</view>
		<view class="input-row">
			<view class="input-title">商户</view>
			<ys-select :selectcontent='merchantsOptions' placeholderText='请选择商户' num='6' :allnum='allnum'></ys-select>
		</view>
	</view>
</template>

<script>
	import ysselect from './ys-select.vue'
	export default {
		components:{
			'ys-select':ysselect
		},
		data() {
			return {
				driverTypeOptions:[
					{id:1,name:'1'},
					{id:2,name:'2'}
				],
				driverOptions:[],
				carTypeOptions:[
					{id:1,name:'1'},
					{id:2,name:'2'}
				],
				carOptions:[],
				escortOptions:[], 
				recycleOptions:[],
				merchantsOptions:[],
				DriverTypeVal:'', 
				allnum:6,  //选择框的个数
			};
		}
	};
</script>

<style>
	.input-row{
		position: relative;
		display: flex;
		align-items: center;
		padding: 0 0 30rpx 24rpx;
	}
	.input-title{
		padding-right: 20rpx;
	}
	.input-title::before{
		content: '*';
		font-size: 40rpx;
		color: red;
		position: absolute;
		left: 0;
		top: 14rpx;
	}
</style>

store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
		isjiantou0:true,
		isjiantou1:true,
		isjiantou2:true,
		isjiantou3:true,
		isjiantou4:true,
		isjiantou5:true,
		isjiantou6:true,
	},
    mutations: {
		getjiantou0(state,n){
			state.isjiantou0=n
		},
		getjiantou1(state,n){
			state.isjiantou1=n
		},
		getjiantou2(state,n){
			state.isjiantou2=n
		},
		getjiantou3(state,n){
			state.isjiantou3=n
		},
		getjiantou4(state,n){
			state.isjiantou4=n
		},
		getjiantou5(state,n){
			state.isjiantou5=n
		},
		getjiantou6(state,n){
			state.isjiantou6=n
		}
	},
    actions: {
		getjiantou0(context,args){
			context.commit('getjiantou0',args);
		},
		getjiantou1(context,args){
			context.commit('getjiantou1',args);
		},
		getjiantou2(context,args){
			context.commit('getjiantou2',args);
		},
		getjiantou3(context,args){
			context.commit('getjiantou3',args);
		},
		getjiantou4(context,args){
			context.commit('getjiantou4',args);
		},
		getjiantou5(context,args){
			context.commit('getjiantou5',args);
		},
		getjiantou6(context,args){
			context.commit('getjiantou6',args);
		},
	}
})
export default store

Note: template string.

If you want to output this.isjiantou0 this.isjiantou1 this.isjiantou2 ... in js, you can use a template string

//`${'jiantou' + i}`
//this[`${'jiantou' + i}`]   这个就相当于this.isjiantou0 所以输出的时候直接是值

for(var i=0;i<6;i++){
    console.log(`${'jiantou' + i}`)  //isjiantou0
    console.log(this[`${'jiantou' + i}`])  //true / false
}

Guess you like

Origin blog.csdn.net/WeiflR10/article/details/126948566