总体效果如上图 所示
一开始直接将address.js 获取的省列表 直接用 filter进行过滤但, 只能过滤 第一个字匹配的, eg: 假如我的搜索 中输入“ 河” 可以过滤出来 “ 河”开头的所有省, 但是输入‘南’, 并不会出现含南的所有的省, 所以经思考 将map 和filter 结合,可以搜出来 所有匹配出来的值,分享给大家 ,下面是所有代码
address.js 可以去我的CSDA上面去下载所有的省市,看下效果
父组件index.vue
<SingleSelectSearch class="fl pr-5" :optionData="provinceData" :selectValue.sync="selectValue" placeholderText="请选择一个城市"/>
子组件singleSelectSearch.vue
<template>
<div>
<el-select
v-model="value7"
:placeholder="placeholderText"
class="select-input_w_middle single-select-search-wrap"
:class="{'single-select-search-wrap-nodata': options3[1].options.length === 0}"
clearable
:popper-append-to-body="false"
@change="changeVal"
@visible-change="visibleChange">
<el-option-group
v-for="(group, index) in options3"
:key="index"
:label="group.label">
<div class="select-search" v-if="index === 0">
<div class="select-search-input">
<el-input
v-model="searchInput"
placeholder="搜索"
prefix-icon="el-icon-search"
@change="searchInputChange"
/>
</div>
<div class="select-search-nodata" v-if="options3[1].options.length === 0">
无数据
</div>
</div>
<el-option
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-option-group>
</el-select>
</div>
</template>
<script>
export default {
props: {
optionData: {
type: Array,
default: function() {
return []
}
},
placeholderText: {
type: String,
default: '请选择'
}
},
watch: {
optionData: {
handler() {
// console.log(this.optionData, '99999')
}
},
searchInput: {
handler() {
// console.log(this.searchInput, '99999')
this.flilterSelectData()
}
}
},
data() {
return {
searchInput: '',
options3: [{
label: '',
options: [{}]
}, {
label: '',
options: []
}],
value7: '',
oldOptionData: []
};
},
created() {
// console.log(this.optionData, '99999')
},
mounted() {
if (this.optionData.length === 0) {
this.options3[0].options = []
}
this.oldOptionData = this.optionData
this.options3[1].options = this.optionData
},
methods: {
changeVal(val) {
this.$emit('update:selectValue', val)
},
searchInputChange(val) {
// console.log('searchInputChange', val)
// this.searchInput = ''
// this.options3[1].options = this.oldOptionData
},
// 过滤下拉选项的值 --- 做到了模糊搜索
flilterSelectData() {
if (this.searchInput === '') {
this.options3[1].options = this.oldOptionData
} else {
var newarray = this.oldOptionData.map(item => {
if (item.label === this.searchInput || item.label.indexOf(this.searchInput) === 0) {
return item;
} else {
for (var i = 0; i < item.label.length; i++) {
if (item.label[i].indexOf(this.searchInput) >= 0) {
return item;
}
}
}
}).filter(item => item)
this.options3[1].options = newarray
}
},
visibleChange(val) {
if (val) {
this.$nextTick(() => {
this.searchInput = ''
})
}
}
},
}
</script>
<style lang='scss' scoped>
.select-search{
.select-search-input{
border-bottom: 1px solid #e8e8e8;
}
}
.select-search-nodata{
line-height: 32px;
padding: 0px 10px;
text-align: center;
color: #999;
}
</style>
element-ui 的样式重置
// 单选加搜索框的
.single-select-search-wrap{
.el-select-group__wrap{
&:nth-child(1) {
height: 33px;
overflow: hidden;
display: block;
}
&:nth-child(2) {
.el-select-group{
padding: 0px 0px 6px;
}
}
}
&.single-select-search-wrap-nodata{
.el-select-group__wrap{
&:nth-child(1) {
height: 65px;
overflow: hidden;
}
}
}
.el-select-dropdown__list{
padding: 0px;
}
.el-select-group__wrap:not(:last-of-type){
padding-bottom: 0px;
}
.el-select-group__wrap:not(:last-of-type)::after{
background-color: transparent;
}
.select-search{
.el-input__inner{
border: 1px solid transparent;
}
.el-input__prefix{
top: -2px;
left: 9px;
}
.el-input--prefix .el-input__inner{
padding-left: 34px;
}
}
.el-select-dropdown__item{
padding: 0px 10px;
}
.el-select-group .el-select-dropdown__item {
padding-left: 10px;
}
}