滚动对话框内容,已打开的下拉框超出对话框范围显示

发布时间 2023-11-20 10:32:10作者: shayloyuki

问题场景

点击对话框内的下拉框,显示下拉列表,纵向滚动对话框内容,已经打开的下拉列表,超出对话框范围仍然显示。

image

分析

下拉框列表消失的条件是下拉框失焦。

因此,有三种解决方案:

  1. 给对话框设置样式:下拉框超出对话框范围就隐藏;
  2. 给对话框内的下拉框设置:若滚动对话框,则让下拉框失焦,即关闭已打开的下拉框;
  3. 滚动对话框,若滚动的距离超出一定范围,就设置下拉框列表样式为隐藏。

解决

这里采用了第三种方案。因为二次封装了对话框组件 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");
    },
   }

弊端

上述代码,滚动距离超出盒子高度,则隐藏下拉框。有两个弊端:

  1. 滚动距离小于盒子高度时:但打开的下拉框位于对话框顶部,此时应该隐藏下拉框,却没有隐藏。
    image

  2. 滚动距离大于盒子高度时:打开下拉框,只要再滚动一下,下拉框就会隐藏,交互操作有些突兀。
    image

改进

方案一:监听对话框滚动,只要一滚动,就隐藏下拉框;

方案二:监听下拉框是否在对话框的显示范围内,只要一超出,就隐藏下拉框;

方案三:设置超出对话框显示范围的下拉框隐藏。

参考链接

  1. 通过自定义指令,解决弹窗内容滚动时el-select下拉框,超出显示范围问题.
  2. 如何强制让element下拉框失去焦点
  3. el-select 组件失去焦点