You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
4.0 KiB

<template>
<view class="uni-combox">
<view v-if="label" class="uni-combox__label" :style="labelStyle">
<text>{{label}}</text>
</view>
<view class="uni-combox__input-box">
<input class="uni-combox__input" type="text" :placeholder="placeholder" v-model="inputVal" @input="onInput"
@focus="onFocus" @blur="onBlur" />
<uni-icons class="uni-combox__input-arrow" type="arrowdown" size="14" @click="toggleSelector"></uni-icons>
<view class="uni-combox__selector" v-if="showSelector">
<scroll-view scroll-y="true" class="uni-combox__selector-scroll">
<view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0">
<text>{{emptyTips}}</text>
</view>
<view class="uni-combox__selector-item" v-for="(item,index) in filterCandidates" :key="index" @click="onSelectorClick(index)">
<text>{{item}}</text>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import uniIcons from '../uni-icons/uni-icons.vue'
export default {
name: 'uniCombox',
components: {
uniIcons
},
props: {
label: {
type: String,
default: ''
},
labelWidth: {
type: String,
default: 'auto'
},
placeholder: {
type: String,
default: ''
},
candidates: {
type: Array,
default () {
return []
}
},
emptyTips: {
type: String,
default: '无匹配项'
},
value: {
type: String,
default: ''
}
},
data() {
return {
showSelector: false,
inputVal: ''
}
},
computed: {
labelStyle() {
if (this.labelWidth === 'auto') {
return {}
}
return {
width: this.labelWidth
}
},
filterCandidates() {
return this.candidates.filter((item) => {
return item.indexOf(this.inputVal) > -1
})
},
filterCandidatesLength() {
return this.filterCandidates.length
}
},
watch: {
value: {
handler(newVal) {
this.inputVal = newVal
},
immediate: true
}
},
methods: {
toggleSelector() {
this.showSelector = !this.showSelector
},
onFocus() {
this.showSelector = true
},
onBlur() {
setTimeout(() => {
this.showSelector = false
},50)
},
onSelectorClick(index) {
this.inputVal = this.filterCandidates[index]
this.showSelector = false
this.$emit('input', this.inputVal)
},
onInput() {
setTimeout(() => {
this.$emit('input', this.inputVal)
})
}
}
}
</script>
<style lang="scss" scoped>
.uni-combox {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
height: 80rpx;
flex-direction: row;
align-items: center;
// border-bottom: solid 2rpx #DDDDDD;
}
.uni-combox__label {
font-size: 32rpx;
line-height: 44rpx;
padding-right: 20rpx;
color: #999999;
}
.uni-combox__input-box {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
align-items: center;
}
.uni-combox__input {
flex: 1;
font-size: 32rpx;
height: 44rpx;
line-height: 44rpx;
}
.uni-combox__input-arrow {
padding: 20rpx;
}
.uni-combox__selector {
box-sizing: border-box;
position: absolute;
top: 84rpx;
left: 0;
width: 100%;
background-color: #FFFFFF;
border-radius: 12rpx;
box-shadow: #DDDDDD 8rpx 8rpx 16rpx, #DDDDDD -8rpx -8rpx 16rpx;
z-index: 2;
}
.uni-combox__selector-scroll {
max-height: 400rpx;
box-sizing: border-box;
}
.uni-combox__selector::before {
content: '';
position: absolute;
width: 0;
height: 0;
border-bottom: solid 12rpx #FFFFFF;
border-right: solid 12rpx transparent;
border-left: solid 12rpx transparent;
left: 50%;
top: -12rpx;
margin-left: -12rpx;
}
.uni-combox__selector-empty,
.uni-combox__selector-item {
/* #ifdef APP-NVUE */
display: flex;
/* #endif */
line-height: 72rpx;
font-size: 28rpx;
text-align: center;
border-bottom: solid 2rpx #DDDDDD;
margin: 0rpx 20rpx;
}
.uni-combox__selector-empty:last-child,
.uni-combox__selector-item:last-child {
border-bottom: none;
}
</style>