组件实现功能 : 1.能模糊搜索并查询到对应的数据项
2.如果没有查询到结果或者输入框失去焦点,自动保存上一次搜索的值
3.可下拉加载更多数据
效果图如下:
1.子组件代码
<template>
<view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'" >
<view class="uni-combox__input-box">
<view v-if='!isShowInput' class="warp_input" @click="clickInput">
<text style="font-size: 15px;color: #C0C4CC;" v-if="!text">{{placeholder}}</text>
<text style="font-size: 15px;" v-else>{{text}}</text>
</view>
<view class="textarea-input" v-else>
<u--textarea
:placeholderStyle='placeholderStyleText'
autoHeight
focus
type="text"
:placeholder="inputValPlaceholder" ref="input"
v-model="inputVal" @input="onChange" @focus="onFocus" @blur="onBlur" />
</view>
</view>
<view class="uni-combox__selector" :style="{left:folatLeft}" v-if="showSelector && dataList.length !== 0">
<view class="mask_select" @click="onClickMask"></view>
<view class="uni-popper__arrow"></view>
<view class="u_list_style">
<u-list @scrolltolower="scrolltolower" height="auto">
<u-list-item v-for="(item , index ) in dataList" :key="index">
<u-cell :title="item[valueKey]" @click="onSelectorClick(index)"></u-cell>
</u-list-item>
</u-list>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'eScorllSelect',
props: {
// placeholderStyle: { //输入框placeholder状态的样式
// type: String,
// default: 'font-size:14px;color:#C0C4CC',
// // default: ''
// },
// selectPosition: { //是否在组件父元素添加定位 默认relative
// type: String,
// default: 'relative'
// },
disabled:{
type: Boolean, //默认显示下边框
default: false
},
folatLeft:{
type: String,
default: '-200rpx'
},
valueKey: { //父组件data数据需要在列表中渲染的key值
type: String,
default: 'companyName'
},
border: {
type: Boolean, //默认显示下边框
default: true
},
label: {
type: String, //选择器label 不建议使用
default: ''
},
labelWidth: { //选择器label宽度 不建议使用
type: String,
default: 'auto'
},
placeholder: { //选择器placeholder文本
type: String,
default: ''
},
candidates: { //选择器下拉框数据 格式为[{}]
type: Array,
default:function(){return []}
},
emptyTips: { //选择器下拉框数据为空文本 ---已注释掉 需要的可以手动打开
type: String,
default: '无匹配项'
},
value: {
type: [String, Number],
default: ''
},
myMessage: { //父组件的值
type: [String, Number],
default: ''
},
},
data() {
return {
placeholderStyleText:'fontSize:14px;color:#C0C4CC',
text:"",
dataList:[],
showSelector: false,
placeholderCopy: '',
inputVal: '',
inputValCopy:'',
isShowInput:false,
inputValPlaceholder:"",
input:""
}
},
computed: {
labelStyle() {
if (this.labelWidth === 'auto') {
return ""
}
return `width: ${this.labelWidth}`
},
},
watch: {
myMessage: {
handler(newVal) {
this.text = newVal
},
immediate: true,
},
candidates:{
handler(value){
this.dataList = value
},
deep:true,
}
},
methods: {
toggleSelector() {
this.showSelector = !this.showSelector
},
clickInput(){
this.isShowInput = true
this.inputValPlaceholder = this.text || this.placeholder
this.inputVal = ''
},
clickShowSelect(){
if(this.disabled) return
this.isShowInput = true
},
onClickMask(e){
this.showSelector = false;
this.isShowInput = false;
this.inputVal = ''
setTimeout(() => {
this.$emit('blur')
}, 153)
},
onFocus() {
if(this.inputValCopy){
this.placeholderCopy = this.inputValCopy
}else{
this.placeholderCopy = this.placeholder
}
this.showSelector = true
},
onBlur() {
},
onSelectorClick(index) {
this.showSelector = false
this.isShowInput = false
this.$emit('update:myMessage', this.dataList[index][this.valueKey])
this.$emit('select', this.dataList[index])
},
as() {
this.$emit('input', this.inputVal)
},
scrolltolower() {
this.$emit('srolltolower')
},
onChange(e) {
this.dataList = []
uni.$u.debounce(this.as, 200)
}
}
}
</script>
<style lang="scss" scoped>
.wraper-inpu-text{
display: flex;
align-items: center;
width: 100%;
flex: 1;
}
.mask_select{
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: -1;
bottom: 0;
background-color: ggba(0,0,0,.2);
}
.warp_input{
width: 100%;
}
.textarea-input{
width: 100%;
}
.uni-combox {
position: relative;
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
width: 100% !important;
}
.uni-combox__label {
padding-right: 10px;
color: #999999;
}
.uni-combox__input-box {
position: relative;
display: flex;
flex: 1;
flex-direction: row;
align-items: center;
}
.uni-combox__input {
flex: 1;
}
.uni-combox__input-plac {
text-align: left;
color: rgb(180, 180, 180);
}
.uni-combox__selector {
box-sizing: border-box;
position: absolute;
top: calc(100% + 12px);
// left: -200rpx;
right: 0;
// width: 100%;
background-color: #FFFFFF;
border: 1px solid #EBEEF5;
border-radius: 6px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
padding: 4px 0;
z-index: 99999999;
}
.uni-combox__selector-scroll {
max-height: 200px;
box-sizing: border-box;
}
.uni-combox__selector-empty,
.uni-combox__selector-item {
display: flex;
cursor: pointer;
font-size: 14px;
text-align: center;
padding: 0px 10px;
}
.uni-combox__selector-item:hover {
background-color: #f9f9f9;
}
.uni-combox__selector-empty:last-child,
.uni-combox__selector-item:last-child {
border-bottom: none;
}
// picker 弹出层通用的指示小三角
.uni-popper__arrow,
.uni-popper__arrow::after {
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 6px;
}
.uni-popper__arrow {
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
top: -6px;
left: 10%;
margin-right: 3px;
border-top-width: 0;
border-bottom-color: #EBEEF5;
}
.uni-popper__arrow::after {
content: " ";
top: 1px;
margin-left: -6px;
border-top-width: 0;
border-bottom-color: #fff;
}
.uni-combox__no-border {
border: none;
}
.u_list_style{
min-height: 0 !important;
max-height: 350rpx !important;
height: auto !important;
display: flex;
}
.mask_click{
position: absolute;
background-color: transparent;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: 9;
}
</style>
2.父组件代码
<u-form-item label="机床厂家" prop="macInfo.macFactory" required borderBottom>
<e-scorll-select
:myMessage.sync="formData.macInfo.macFactory"
:candidates='repairCompList'
:placeholderStyle='placeholder'
selectPosition='static'
valueKey="compName"
@select='macChange'
@srolltolower='srolltolowerCompList'
@input='searchInputRepair'
placeholder='请选择机床厂家'
>
</e-scorll-select>
</u-form-item>
searchInputRepair(e){
this.repairCompList = []
this.repaireCompPgae.pageNum = 1
this.repaireCompPgae.param = e
this.getMacCompanyList(e)
},
srolltolowerCompList(){
if (this.repairCompTotal > this.repairCompList['length']) {
this.repaireCompPgae.pageNum++
this.getMacCompanyList()
}
},
macChange(e) {
this.formData.macInfo.factoryAreaId = e.areaId
},
参数说明:
属性
myMessage.sync:父子组件进行数据双向绑定(因为小程序不支持model属性,无法在父元素身上添加v-model)
candidates:数据源
placeholderStyle:选择器输入框样式(有需要的自己在子组件去开启)
placeholder:选择器提示文字
valueKey:数据源中需要渲染的值
selectPosition:定位标准
事件
@srolltolower 数据框下拉事件;(做分页加载);
@input 输入事件 ;(做模糊搜索)
@select 数据项选中事件 (选中其中一项)
说明:如果跟自己的项目需求有区别,完全可以对子组件进行改造;
咱门都是干前端的兄弟姐妹,只是想把一些方便的东西分享给大家,免得浪费大量时间去弄这种挺S*的组件,目前可能封装的不是很完善,还很粗糙,单后面还会花时间的去优化改造,最终形成一个稳定的版本。