一,自定义的el-select可查询可根据字母进行筛选类似联系人列表
<template>
<el-select v-model="selectedProvince" filterable remote :remote-method="queryProvinces" placeholder="请选择省份"
clearable @visible-change="visibleChange" @visible="handleVisible" class="custom-select "
:popper-append-to-body='false'>
<div class="alphabet-column">
<div v-for="letter in letters" :key="letter" @click="scrollToProvince(letter)">
{{ letter }}
</div>
</div>
<el-option-group v-for="(group, index) in sortedProvinceGroups" :key="index" :label="group.letter">
<el-option v-for="province in group.provinces" :key="province.id" :label="province.name"
:value="province.id" :ref="`provinceOption-${province.id}`"></el-option>
</el-option-group>
</el-select>
</template>
<script>
export default {
data() {
return {
selectedProvince: '', // 绑定选中的省份
selectedLetter: '',
provinces: [],
letters: ['A', 'B', 'C', 'F', 'G', 'H', 'J', 'L', 'N', 'Q', 'S', 'T', 'X', 'Y', 'Z'] // 字母数组
};
},
mounted() {
this.provinces = [
{ id: 1, name: '北京', letter: 'B' },
{ id: 2, name: '天津', letter: 'T' },
{ id: 3, name: '河北', letter: 'H' },
{ id: 4, name: '山西', letter: 'S' },
{ id: 5, name: '内蒙古', letter: 'N' },
{ id: 6, name: '辽宁', letter: 'L' },
{ id: 7, name: '吉林', letter: 'J' },
{ id: 8, name: '黑龙江', letter: 'H' },
{ id: 9, name: '上海', letter: 'S' },
{ id: 10, name: '江苏', letter: 'J' },
{ id: 11, name: '浙江', letter: 'Z' },
{ id: 12, name: '安徽', letter: 'A' },
{ id: 13, name: '福建', letter: 'F' },
{ id: 14, name: '江西', letter: 'J' },
{ id: 15, name: '山东', letter: 'S' },
{ id: 16, name: '河南', letter: 'H' },
{ id: 17, name: '湖北', letter: 'H' },
{ id: 18, name: '湖南', letter: 'H' },
{ id: 19, name: '广东', letter: 'G' },
{ id: 20, name: '广西', letter: 'G' },
{ id: 21, name: '海南', letter: 'H' },
{ id: 22, name: '重庆', letter: 'C' },
{ id: 23, name: '四川', letter: 'S' },
{ id: 24, name: '贵州', letter: 'G' },
{ id: 25, name: '云南', letter: 'Y' },
{ id: 26, name: '西藏', letter: 'X' },
{ id: 27, name: '陕西', letter: 'S' },
{ id: 28, name: '甘肃', letter: 'G' },
{ id: 29, name: '青海', letter: 'Q' },
{ id: 30, name: '宁夏', letter: 'N' },
{ id: 31, name: '新疆', letter: 'X' },
{ id: 32, name: '台湾', letter: 'T' },
{ id: 33, name: '香港', letter: 'X' },
{ id: 34, name: '澳门', letter: 'A' }
]
},
computed: {
sortedProvinceGroups() {
// 如果没有选择字母,则返回所有省份分组
if (!this.selectedLetter) {
// 根据首字母对省份数据进行分组和排序
const sortedProvinces = this.provinces.sort((a, b) => a.letter.localeCompare(b.letter));
const groups = {};
sortedProvinces.forEach(province => {
const letter = province.letter;
if (!groups[letter]) {
groups[letter] = [];
}
groups[letter].push(province);
});
return Object.keys(groups).map(letter => ({ letter, provinces: groups[letter] }));
}
// 只返回选定字母对应的省份组
return this.provinces
.filter(province => province.letter === this.selectedLetter)
.map(province => ({ letter: province.letter, provinces: [province] }));
}
},
methods: {
// 点击字母滚动到对应省份位置
scrollToProvince(letter) {
this.selectedLetter = letter;
console.log(letter)
const targetProvince = this.provinces.find(province => province.letter === letter);
if (targetProvince) {
const targetRef = this.$refs[`provinceOption-${targetProvince.id}`]; // 获取对应的 ref
if (targetRef) {
console.log(targetRef, 'ref')
targetRef.$el.scrollIntoView();
}
}
},
// 远程搜索函数
queryProvinces(query) {
// 模拟异步请求,实际中应该发送请求到后端进行检索
setTimeout(() => {
// 根据输入内容查询匹配的省份
const matchedProvinces = this.provinces.filter(province => province.name.includes(query));
// 将查询结果传递给 el-select 组件
this.provinces = matchedProvinces;
}, 300); // 模拟延迟
},
// 处理下拉框显示事件
handleVisible(visible) {
if (visible) {
// 下拉框显示时,滚动到第一个省份
this.$nextTick(() => {
const firstProvince = this.provinces[0];
if (firstProvince) {
const targetRef = this.$refs[`provinceOption-${firstProvince.id}`]; // 获取对应的 ref
if (targetRef) {
targetRef.$el.scrollIntoView();
}
}
});
}
},
// 处理下拉框显示/隐藏变化事件
visibleChange(visible) {
if (!visible) {
// 下拉框隐藏时,重置搜索条件
// 这里你可以根据需要进行其他操作,比如清空搜索框内容等
this.selectedLetter = "";
}
}
}
};
</script>
<style scoped>
.custom-select .el-input__inner {
padding-right: 30px;
/* 增加右侧间距 */
}
.alphabet-column {
display: flex;
flex-direction: column;
position: absolute;
right: 5px;
/* 调整位置 */
top: 0;
bottom: 0;
padding-top: 10px;
/* 调整上下内边距 */
pointer-events: none;
/* 不影响下拉框的点击事件 */
z-index: 1;
/* 设置 z-index,确保在选项之上 */
font-size: 10px;
}
.alphabet-column div {
cursor: pointer;
margin-bottom: 5px;
pointer-events: auto;
/* 恢复点击事件 */
}
/deep/.el-select-dropdown__wrap {
min-height: 280px !important;
text-align: start;
}
/* 调整选项的样式,确保不遮挡右侧字母列 */
.el-select-dropdown .el-scrollbar__wrap {
overflow: visible !important;
}
.el-select-dropdown .el-option {
overflow: visible !important;
}
.el-select-dropdown .el-option__content {
overflow: visible !important;
}
.el-select-dropdown .el-option__content:hover {
background-color: transparent !important;
/* 鼠标悬停时取消背景色 */
}
</style>