做这个功能的初衷是因为elementUI的select框带(搜索功能的)操作不是很便捷。比如:在选择值后,按键盘下键从头开始往后选择等。
功能实现的大体思路是:
1 键盘上下移动选中项跟着移动
2 当移动项超出设定高度时,分为两种情况:①继续向下滚动,滚动项始终在最底部;②继续向上滚动,滚动项始终在最顶部
3.按enter键确认值,按键盘下键定位到该确认值
html结构:
<div class="select-title">
<el-input
type="textarea"
v-model="searchText"
@keydown.native.down.stop.prevent="navigateOptions('next')"
@keydown.native.up.stop.prevent="navigateOptions('prev')"
@keydown.native.enter.prevent="selectOption"
></el-input>
</div>
<div class="select-content" ref="selectContent" v-if="showContent">
<div class="select-option">
<div
class="option-item"
v-for="(item, index) in optionList"
:key="index"
@click="handleOption(item)"
>
{{ item.initLabel }}
</div>
</div>
</div>
上下移动js:
/**
* direction:移动方向
* hasFocusOption:是否是聚焦定位选项(区分上下移动定位选项)
*/
navigateOptions(direction, hasFocusOption) {
if (this.optionList.length === 0 || this.subVisible) return
if (!this.showContent && !this.subVisible) {
this.$emit('update:showContent', true)
return
}
if (!hasFocusOption) {
if (direction === 'next') {
this.hoverIndex++
if (this.hoverIndex === this.optionList.length) {
this.hoverIndex = 0
}
// 第一项到当前选中项高度大于滚动高度加下拉框高度
if ((this.hoverIndex + 1) * 25 >= document.querySelector('.select-option').scrollTop + 180)
document.querySelector('.select-option').scrollTop = (this.hoverIndex + 1) * 25 - 180
else if (this.hoverIndex === 0) document.querySelector('.select-option').scrollTop = 0
} else if (direction === 'prev') {
this.hoverIndex--
if (this.hoverIndex < 0) {
this.hoverIndex = this.optionList.length - 1
}
// 第一项到当前选中项前一项高度小于滚动高度
if ((this.hoverIndex + 1) * 25 - 25 <= document.querySelector('.select-option').scrollTop)
document.querySelector('.select-option').scrollTop = (this.hoverIndex + 1) * 25 - 25
else if (this.hoverIndex === this.optionList.length - 1)
document.querySelector('.select-option').scrollTop = (this.hoverIndex + 1) * 25 - 180
}
} else {
// 第一项到当前选中项高度大于下拉框高度
if ((this.hoverIndex + 1) * 25 > 180)
document.querySelector('.select-option').scrollTop = (this.hoverIndex + 1) * 25 - 180
else document.querySelector('.select-option').scrollTop = 0
}
let optionItems = this.$refs.selectContent.querySelectorAll('.option-item')
optionItems.forEach((item, index) => {
item.classList.remove('activeOption')
if (index === this.hoverIndex) item.classList.add('activeOption')
})
},
enter确认js:
selectOption() {
// 这里将选中值传到输入框即可
...
},
按键盘下键定位选中项位置:
this.optionList.forEach((item, index) => {
if (item.initLabel === this.searchText) {
this.hoverIndex = index
this.navigateOptions('', true)
return
}
})
最终效果展示:
处理这个问题还有另一种方式,就是修改elementUI的源码,具体可以参考这篇文章:https://www.jianshu.com/p/21e492fb9eff