<template>
<div>
<el-select
v-el-select-loadmore="deLoadMore"
v-show="isShowSelect"
v-model="selectedValue"
v-bind="$attrs"
ref="oSelect"
@change="changeHandler"
@visible-change="visibleChange"
:disabled="disabled"
class="width100"
:placeholder="placeholder"
>
<!-- 表头 -->
<el-option
v-if="selectOptions.length && labelParams.length > 1"
disabled
:key="new Date().getTime()"
:value="new Date().getTime()"
>
<div class="header">
<div
v-for="(item, index) in headerLabel"
:key="index"
:style="`display: inline-block;width:${columnWidth[index]}`"
:class="{ ml20: index != 0, option: true }"
>
{{ item }}
</div>
</div>
</el-option>
<!-- 选项,支持一列或多列,由labelParams的元素个数决定 -->
<el-option
v-for="(item,index) in selectOptions"
:key="`opt-${index}`"
:value="isItemNotObj ? item : item[valueName]"
:label="isItemNotObj ? item : (item[defaultLabel] || item[labelParams[0]])"
>
<div class="header">
<div
v-for="(params, index) in labelParams"
:key="index"
:style="`display: inline-block;width:${columnWidth[index]}`"
:class="{ ml20: index != 0, option: true }"
>
{{ isItemNotObj ? item : item[params] }}
</div>
</div>
</el-option>
<!-- <el-option
v-for="item in selectOptions"
:key="item[valueName]"
:value="item[valueName]"
:label="item[labelName]"
>
</el-option> -->
</el-select>
<el-input :placeholder="placeholder" v-show="!isShowSelect" v-model="inputLabel" @click.native="changeVisible" readonly :disabled="disabled"></el-input>
</div>
</template>
<script>
import { debounce } from "@/utils/index.js"
export default {
name: "InfoSelect",
/**
* !!!不支持多选
*/
props: {
placeholder:{
default: '请选择',
type: [String, Number]
},
//如果option数组的元素不是对象,将此项置为true。为true时不需传valueName和labelParams
isItemNotObj:{
default: false,
type: Boolean
},
value: {
// required: true,
type: [String, Number]
},
//输入框显示值
inputLabel: {
default: ""
},
// 选项,option列表
selectOptions: {
type: Array,
default: () => []
},
//option的value变量名
valueName: {
default: 'value'
},
// 设置每列宽度
columnWidth: {
type: Array,
default: function (){
return ['200px', '200px']
}
},
// 表头显示文字(只有一列时不显示)
headerLabel: {
type: Array,
default: () => [],
},
//每一列label的变量名(只有一列就输入一个元素)
labelParams:{
type: Array,
default: () => ['label']
},
disabled:{
type: Boolean,
default: false
},
//选中某一项后,select中显示的字段,不传的话默认为labelParams的第一项
defaultLabel:{
default: ""
}
},
data() {
return {
//是否正在展示select
isShowSelect: false,
// 触底事件
deLoadMore: debounce(this.loadMore, 100)
}
},
computed:{
// el-select的v-model
selectedValue:{
get(){
return this.value
},
set(newVal){
this.$emit('input', newVal)
}
}
},
methods: {
loadMore() {
// 防止搜索结果太少时,触发“滚动条触底”事件
if (this.selectOptions.length <= 6) return
let input = this.$refs.oSelect.$children[0].$refs.input;
let keyword = input.value
//触底事件,抛出此时输入框的内容
this.$emit('toBottom', keyword)
},
changeHandler(value) {
let selectedObj = undefined
if(!this.isItemNotObj){
selectedObj = this.selectOptions.find(item => item[this.valueName] == value)
}
// 自定义事件抛出两个参数,第一个为选中的value值,第二个为选中value值所在的对象(清空选择时,selectedObj为undefined)
this.$emit('changes', value, selectedObj)
this.changeVisible()
},
//切换input和select
changeVisible() {
this.isShowSelect = !this.isShowSelect
this.$nextTick(() => {
if (this.isShowSelect) this.$refs.oSelect.focus()
})
},
//下拉框出现/隐藏时触发, visible: 出现则为 true,隐藏则为 false
visibleChange(visible){
if(visible)return
this.isShowSelect = false
}
},
watch: {
isShowSelect: {
handler(newValue) {
// 隐藏select时重置options
if (newValue == false) this.$emit('resetOptions')
}
}
},
mounted() {
}
}
</script>
<style scoped lang="scss">
.header {
display: flex;
}
.option {
display: inline-block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
/deep/ .el-select-dropdown__list {
padding-top: 0 !important;
}
.el-select-dropdown__item.is-disabled {
background: #eff0f2;
}
</style>
父组件调用:
<info-select
v-model="formData.projectId"
:inputLabel="formData.projectName"
:selectOptions="projectList"
@changes="projectSelChange"
@toBottom="projectLoadMore"
filterable
remote
:remote-method="projectRemoteMethod"
@resetOptions="projectResetOptions"
:disabled="isDisabled"
:loading="projectRemoteLoading"
placeholder="请选择项目名称"
:columnWidth="['400px']"
>
</info-select>