Vue element下拉菜单实现键盘事件上下移
2021-07-14 本文已影响0人
爱吃炸鸡的Banana
需求
提高用户体验感,输入框自动聚焦并键盘控制下拉菜单的选项上下移
效果如图:
初期使用的el-dropdown下拉菜单,组件默认可键盘上下移
<el-dropdown
v-if="authoritys.length > 0"
trigger="click"
@visible-change="toggleSchoolDrop"
@command="_changeSchool"
>
<el-dropdown-menu slot="dropdown">
<el-input
v-model="searchSchoolName"
clearable
class="school-input"
size="mini"
:placeholder="$t('el.input.placeholder')"
@input="searchSchool"
/>
<div class="school-menu-list">
<el-dropdown-item
v-for="(s,i) in authoritysList"
v-show="!s.isHide"
:key="i"
:command="s.id"
>
{{ i < 9 ? `0${i + 1}` : i + 1 }}. {{ s.name }}
</el-dropdown-item>
</div>
</el-dropdown-menu>
</el-dropdown>
但是键盘按上下移不生效.
可能因为我的el-dropdown-item是由数组遍历出来的,文档的菜单是写死的.
换成el-popover组件,内部用ul和li实现遍历菜单.
<el-popover
v-if="authoritys.length > 0"
v-model="visible"
trigger="click"
@visible-change="toggleSchoolDrop"
>
<el-input
v-model="searchSchoolName"
clearable
class="school-input mr-b-m"
size="mini"
:placeholder="$t('el.input.placeholder')"
@input="searchSchool"
/>
<ul
id="school-menu-list"
class="school-menu-list"
>
<li
v-for="(s,i) in authoritysList"
v-show="!s.isHide"
:key="i"
class="result-option"
:class="{'is-active': i===activeIndex,'selectActive': i===selectIndex}"
@mouseover="_handleMouseOver(i)"
@click="_changeSchool(s.id,i)"
>
{{ i < 9 ? `0${i + 1}` : i + 1 }}. {{ s.name }}
</li>
</ul>
</el-popover>
后续需要在input框自动聚焦后再触发键盘上下移事件.
实现自动聚焦,首先想到的方法是 给el-input 添加ref,获取后调用focus()
<el-input
placeholder="请输入内容"
v-model="value"
clearable
@keyup.enter.native="confirm"
ref="sInput"
>
this.$refs.sInput.focus()
但是不生效,
后续查看element官方文档可用popover的show event手动给el-input获取焦点
<el-popover placement="bottom" width="200" trigger="manual" v-model="visible" @show="onShow">
<el-input
placeholder="请输入内容"
v-model="value"
clearable
@keyup.enter.native="confirm"
ref="sInput"
>
</el-popover>
methods: {
onShow () {
this.$refs.sInput.focus()
}
}
还是不生效,
对焦需要下拉打开后执行,也就是dom更新后所以添加 this.$nextTick生效
methods: {
onShow () {
this.$nextTick(() => {
this.$refs.sInput.focus()
});
}
}
完成搜索输入框的自动对焦后添加键盘事件,
添加的键盘事件让用户看到选择的选项样式变化以外,滚轮是不会变动的,
继续提升用户体验感,需要让滚轮随着用户的操作而滑动
<el-input
ref="searchSchool"
v-model="searchSchoolName"
clearable
class="school-input mr-b-m"
size="mini"
:placeholder="$t('el.input.placeholder')"
@input="searchSchool"
@keyup.enter.native="_handleEnter(selectIndex)"
@keyup.up.native="_handleUp"
@keyup.down.native="_handleDown"
/>
methods: {
_handleUp(){
// 实现对样式的替换
this.selectIndex = this.selectIndex === 0 ? this.authoritysList.length - 1 : this.selectIndex - 1;
let selectNum = this.selectIndex + 1;
let schoolMenuList = document.getElementById("school-menu-list");
let intervalTop = schoolMenuList.scrollTop;
// 实现在用户操作是,滚轮随着上下移的动
if (selectNum * 35 <= intervalTop){
schoolMenuList.scrollTop = (selectNum - 1) * 35;
} else if (selectNum * 35 <= intervalTop + schoolMenuList.offsetHeight){
schoolMenuList.scrollTop = intervalTop;
} else if (selectNum * 35 > intervalTop){
schoolMenuList.scrollTop = selectNum * 35;
}
},
_handleDown(){
this.selectIndex = this.selectIndex < this.authoritysList.length - 1 ? this.selectIndex + 1 : 0;
let selectNum = this.selectIndex + 1;
let schoolMenuList = document.getElementById("school-menu-list");
let intervalTop = schoolMenuList.scrollTop;
if (selectNum * 35 <= intervalTop){
schoolMenuList.scrollTop = (selectNum - 1) * 35;
} else if (selectNum * 35 <= intervalTop + schoolMenuList.offsetHeight){
schoolMenuList.scrollTop = intervalTop;
} else if (selectNum * 35 > intervalTop){
schoolMenuList.scrollTop = selectNum * 35 - schoolMenuList.offsetHeight;
}
}
}