bug出现场景-:
场景描述:在发生滚动时下拉框滚动出弹窗
原因分析: 没有做监听事件来控制下拉框的显示隐藏
bug出现场景二:
场景描述:在增加滚动事件监听、已解决场景-bug的基础上。切换浏览器标签页、或者切换应用后又重新回到当前页面。此时下拉框再次错位出现
原因分析:切换窗口,浏览器会主动聚焦上次聚焦的input框
解决方案:
思路:
1、针对场景一可增加滚动事件监听
2、针对场景二:动态设置el-select的filterable值。阅读el-select源码可以知道,浏览器主动聚焦时,调用了handleFoucs事件,当filterable为true时,会设visible为true(下拉框的v-show的值)。可通过调整filterable的状态来达到更新visible的值。el-select关键源码展示
handleFocus(event) {
if (!this.softFocus) {
if (this.automaticDropdown || this.filterable) {
if (this.filterable && !this.visible) {
this.menuVisibleOnFocus = true;
}
this.visible = true;
}
this.$emit('focus', event);
} else {
this.softFocus = false;
}
},
bug修复代码展示:
/**
* 自定义鼠标up、down事件
* 因为在el-select 的自定义指令中v-clickoutside的实现就是,在点击其他区域,触发handleClose,下拉框收起
* 这里自定义事件,为了主动触发事件。调用handleClose
*/
const MousedownEvent = new Event('mousedown', { bubbles: true })
const MouseupEvent = new Event('mouseup', { bubbles: true })
const autoClickOutside = () => {
document.dispatchEvent(MousedownEvent)
document.dispatchEvent(MouseupEvent)
}
/**
* 节流
* @param {} fn
* @returns
*/
function throttle(fn) {
let locked = false
return function(...args) {
locked = true
window.requestAnimationFrame(_ => {
fn.apply(this, args)
locked = false
})
}
}
export default {
data() {
return {
// 由于浏览器会在切换页面返回到当前页时input框会自动聚焦、当filterable=true时导致下拉框自动显示出来,出现UI错位bug,所以动态设置filterable
ifFilterAble: true
}
},
mounted() {
this.$nextTick(() => {
this.throttleScroll = throttle(this.handleScroll, 20)
window.addEventListener('scroll', this.throttleScroll, true)
})
},
destroyed() {
window.removeEventListener('scroll', this.throttleScroll)
},
methods: {
handleScroll(e) {
const classList = e.target.classList
const scrollLeft = e.target.scrollLeft
if (classList.contains('el-select-dropdown__item') || e.target.parentNode.classList.contains('el-select-dropdown__item')) {
return
}
if (scrollLeft > 5) {
this.ifFilterAble = false
autoClickOutside()
} else {
this.ifFilterAble = true
}
}
}
}
vue组件代码展示
<template>
<el-select :filterable="ifFilterAble">
<el-option v-for="(item) in sparts" :key="item.code" :label="item.code" :value="item.code"></el-option>
</el-select>
</template>
<script>
import clickOutsides from '@/mixins/clickOutsides'
export default {
mixins: [clickOutsides],
</script>