问题场景
点击对话框内的下拉框,显示下拉列表,纵向滚动对话框内容,已经打开的下拉列表,超出对话框范围仍然显示。
分析
下拉框列表消失的条件是下拉框失焦。
因此,有三种解决方案:
- 给对话框设置样式:下拉框超出对话框范围就隐藏;
- 给对话框内的下拉框设置:若滚动对话框,则让下拉框失焦,即关闭已打开的下拉框;
- 滚动对话框,若滚动的距离超出一定范围,就设置下拉框列表样式为隐藏。
解决
这里采用了第三种方案。因为二次封装了对话框组件 DialogBox,就直接给 DialogBox 对话框设置隐藏下拉框列表。
computed: {
// 滚动的视图范围
scrollView() {
const el = document.getElementsByClassName("el-dialog__body");
return el.length ? el[0] : null;
},
// 下拉框对象
selectObj() {
let result = {
"el-autocomplete-suggestion": null,
"el-select-dropdown": null,
};
if (!this.scrollView) {
return result;
} else {
Object.keys(result).forEach((key) => {
result[key] = this.scrollView.getElementsByClassName(key);
});
return result;
}
},
},
created() {
this.$nextTick(() => {
// 开始监听
document.addEventListener("scroll", this.handleScroll, true);
});
},
methods: {
// 滚动对话框时,隐藏下拉框
handleScroll() {
let contentHeight = this.scrollView.scrollHeight;
let gridHeight = this.scrollView.clientHeight;
let scrollDistance = this.scrollView.scrollTop;
// console.log({ contentHeight }, { gridHeight }, { scrollDistance });
// 滚动距离超出盒子高度,则隐藏下拉框
if (scrollDistance >= gridHeight) {
Object.keys(this.selectObj).forEach((key) => {
if (!this.selectObj[key]) return;
for (let item of this.selectObj[key]) {
item.style.display = "none";
}
});
}
},
handleClose() {
if (!this.scrollView) return;
// 移除监听
this.scrollView.removeEventListener("scroll", this.handleScroll, true);
this.$emit("close-dialog");
},
}
弊端
上述代码,滚动距离超出盒子高度,则隐藏下拉框。有两个弊端:
-
滚动距离小于盒子高度时:但打开的下拉框位于对话框顶部,此时应该隐藏下拉框,却没有隐藏。
-
滚动距离大于盒子高度时:打开下拉框,只要再滚动一下,下拉框就会隐藏,交互操作有些突兀。
改进
方案一:监听对话框滚动,只要一滚动,就隐藏下拉框;
方案二:监听下拉框是否在对话框的显示范围内,只要一超出,就隐藏下拉框;
方案三:设置超出对话框显示范围的下拉框隐藏。