佰川加油
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.
 
 
 
 

370 lines
8.4 KiB

<template>
<view class="uni-combox">
<view class="uni-combox-dialog" v-if="isDialogInput && showSelector">
<view class="uni-combox-input">
<input
class="uni-combox__input"
type="text"
:placeholder="selectItem.value ? selectItem.value : placeholder"
v-model="inputVal"
@input="onInput"
@blur="onBlur"
:focus="'true'"
style="height: 90upx;"
/>
<uni-icons style="line-height: 90upx;" class="uni-combox__input-arrow" type="close" size="14" @click="clearSelector"></uni-icons>
<view class="uni-combox__selector">
<scroll-view scroll-y="true" class="uni-combox__selector-scroll">
<view class="uni-combox__selector-empty" v-if="isLoading"><text>数据加载...</text></view>
<view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0 && !isLoading">
<text>{{ emptyTips }}</text>
</view>
<view v-if="!isLoading" class="uni-combox__selector-item" v-for="(item, index) in filterCandidates" :key="index" @click="onSelectorClick(item)">
<view class="addr_title">
<text>{{ item.value }}</text>
</view>
<view class="detail_info">
<text>{{item.detail}}</text>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
<view v-if="label" class="uni-combox__label" :style="labelStyle">
<text>{{ label }}</text>
</view>
<view class="uni-combox__input-box">
<input
v-if="isDialogInput"
class="uni-combox__input"
type="text"
:placeholder="selectItem.value ? selectItem.value : placeholder"
v-model="inputVal"
@focus="onFocus"
/>
<input
v-else
class="uni-combox__input"
type="text"
:placeholder="selectItem.value ? selectItem.value : placeholder"
v-model="inputVal"
@focus="onFocus"
@input="onInput"
@blur="onBlur"
/>
<uni-icons v-if="!showSelector && !inputVal" class="uni-combox__input-arrow" type="arrowdown" size="14" @click="toggleSelector"></uni-icons>
<uni-icons v-else class="uni-combox__input-arrow" type="close" size="14" @click="clearSelector"></uni-icons>
<view class="uni-combox__selector" v-if="!isDialogInput && showSelector">
<scroll-view scroll-y="true" class="uni-combox__selector-scroll">
<view class="uni-combox__selector-empty" v-if="isLoading"><text>数据加载...</text></view>
<view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0 && !isLoading">
<text>{{ emptyTips }}</text>
</view>
<view v-if="!isLoading" class="uni-combox__selector-item" v-for="(item, index) in filterCandidates" :key="index" @click="onSelectorClick(item)">
<view class="addr_title">
<text >{{ item.value }}</text>
</view>
<view class="detail_info">
<text >{{item.detail}}</text>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import uniIcons from '../uni-icons/uni-icons.vue';
/**
* Combox 组合输入框
* @description 组合输入框一般用于既可以输入也可以选择的场景
* @tutorial https://ext.dcloud.net.cn/plugin?id=1261
* @property {String} label 左侧文字
* @property {String} labelWidth 左侧内容宽度
* @property {String} placeholder 输入框占位符
* @property {Array} candidates 候选项列表
* @property {String} emptyTips 筛选结果为空时显示的文字
* @property {String} value 组合框的值
* @property {String} isDialogInput 弹出框输入和选择避免键盘遮挡
*/
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: ''
},
isDialogInput: {
type: Boolean,
default: false
}
},
data() {
return {
showSelector: false,
inputVal: '',
isLoading: false,
showDowm: true,
selectItem: { key: '', value: '' }
};
},
computed: {
labelStyle() {
if (this.labelWidth === 'auto') {
return {};
}
return {
width: this.labelWidth
};
},
filterCandidates() {
return this.candidates.filter(item => {
return item;
});
},
filterCandidatesLength() {
return this.filterCandidates.length;
}
},
onLoad() {
if(this.value){
this.inputVal = this.value
console.log("这里是组件内部值为:"+this.inputVal)
}
},
watch: {
value: {
handler(newVal) {
if(newVal) {
this.candidates.filter(item => {
if (this.value === item.key) {
this.selectItem = item;
this.inputVal = item.value;
}
});
}else {
this.selectItem = { key: '', value: '' }
this.inputVal = ''
}
},
immediate: true
},
candidates: {
handler(newVal) {
this.isLoading = false;
},
immediate: true
}
},
methods: {
toggleSelector() {
this.showSelector = !this.showSelector;
},
clearSelector() {
console.log('这里是组件里清除')
this.selectItem = { key: '', value: '' };
this.inputVal = '';
this.showSelector = false;
this.isLoading = false;
this.$emit('clear');
},
onFocus() {
console.log('这里是是input foucus')
if (this.inputVal) {
this.showSelector = false;
// this.inputVal = '';
}
},
// 组件input失焦
onBlur() {
console.log('这里是input失焦')
// this.showSelector = !this.showSelector;
setTimeout(() => {
if (this.selectItem.value) {
console.log('这里是this.selectItem.value',this.selectItem.value)
const selectItem = JSON.parse(JSON.stringify(this.selectItem));
this.inputVal = selectItem.value;
} else {
console.log('123')
this.inputVal = '';
}
// this.showSelector = false;
}, 50);
},
onSelectorClick(item) {
console.log('这类似组件内',item)
this.selectItem = item;
this.inputVal = item.value;
this.showSelector = false;
this.$emit('select', item.key, item);
},
onInput() {
console.log('这类似inputchange',this.inputVal)
setTimeout(() => {
if (this.inputVal && this.inputVal!=='') {
this.isLoading = true;
this.showSelector = true;
this.$emit('input', this.inputVal);
} else {
this.isLoading = false;
}
});
}
}
};
</script>
<style lang="scss" scoped>
.uni-combox {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
height: 40upx;
flex-direction: row;
align-items: center;
// border-bottom: solid 1px #DDDDDD;
}
.uni-combox__label {
font-size: 28upx;
line-height: 40upx;
padding-right: 10px;
color: #999999;
}
.uni-combox__input-box {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
width: 320rpx;
flex-direction: row;
align-items: center;
}
.uni-combox__input {
flex: 1;
font-size: 28upx;
}
.uni-combox__input-arrow {
padding-left: 15upx;
padding-right: 15upx;
}
.uni-combox__selector {
box-sizing: border-box;
position: absolute;
top: 40px;
left: -145rpx;
right: 150rpx;
width: 139%!important;
background-color: #FFFFFF;
border-radius: 6px;
box-shadow: #dddddd 4px 4px 8px, #dddddd -4px -4px 8px;
z-index: 2222;
}
.uni-combox__selector-scroll {
max-height: 550upx;
box-sizing: border-box;
}
.uni-combox__selector::before {
content: '';
position: absolute;
width: 0;
height: 0;
border-bottom: solid 6px #ffffff;
border-right: solid 6px transparent;
border-left: solid 6px transparent;
left: 50%;
top: -6px;
margin-left: -6px;
}
.uni-combox__selector-empty,
.uni-combox__selector-item {
/* #ifdef APP-NVUE */
display: flex;
/* #endif */
line-height: 40upx;
font-size: 28upx;
text-align: center;
border-bottom: solid 1px #dddddd;
padding: 4rpx 9rpx;
margin: 0px 10px;
}
.uni-combox__selector-empty{
line-height: 70upx;
}
.uni-combox__selector-empty:last-child,
.uni-combox__selector-item:last-child {
border-bottom: none;
}
.uni-combox-dialog {
background: #cccccc7d;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 100;
}
.uni-combox-input {
background: #fff;
display: -webkit-box;
display: -webkit-flex;
display: flex;
height: 90upx;
}
.addr_title{
font-weight: 700;
font-size: 30rpx;
text-align: left;
margin-bottom: 0;
padding-bottom: 0;
margin-top: 10rpx;
margin-left: 20rpx;
}
.detail_info{
text-align: left;
color: #CCCCCC;
margin-top: 0;
padding-top: 0;
font-size: 25rpx;
margin-left: 20rpx;
}
</style>