页面滚动时隐藏el-select下拉框(vue+eleme

问题描述:elementUi的el-select下拉选择框,打开之后,直到失去焦点才会自动关闭。 在有滚动条的弹窗中使用时就会出现打开下拉框,滚动弹窗,el-select下拉框会超出弹窗范围的问题.

1.gif

解决方案1. 监听鼠标滚轮事件mousewheel

缺点:手动拖动滚动条时,不起效

// 滚轮事件的监听于移除并返回当前滚轮滚动方向,取消监听执行scrollFunc第二个参数
export function scrollEven(scrollFunc) {
  let isRemove = false
  // 火狐浏览器
  if (document.addEventListener) {
    document.addEventListener('DOMMouseScroll', scroll, false)
  } // W3C
  document.addEventListener('mousewheel', scroll, false) // IE/Opera/Chrome/Safari

  function scroll(e) {
    // direct 是 1 向上,是 -1 向下
    var direct = 0
    e = e || window.event
    if (e.wheelDelta) {
      //IE/Opera/Chrome
      direct = e.wheelDelta > 0 ? 1 : -1
    } else if (e.detail) {
      //Firefox
      direct = e.detail < 0 ? 1 : -1
    }
    if (isRemove) {
      document.removeEventListener('DOMMouseScroll', scroll, false)
      document.removeEventListener('mousewheel', scroll, false) // IE/Opera/Chrome/Safari
    }
    scrollFunc(direct, removeScroll, e)
  }

  function removeScroll() {
    isRemove = true
  }
}

<template>
  <div>
    <el-button type="primary" @click="dialogVisible = true">Click</el-button>
    <el-dialog title="滚动表单" :visible.sync="dialogVisible" width="50%">
      <div style="height: 400px; overflow: auto">
        <el-form ref="form" :model="form" label-width="80px">
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-select ref="mySelect" v-model="form.name" placeholder="">
              <el-option
                v-for="item in 10"
                :key="item"
                :label="item"
                :value="item"
              >
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
        </el-form>
      </div>
      <div slot="footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false"
          >确 定</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { scrollEven } from '@/utils/event.js'
export default {
  data() {
    return {
      dialogVisible: false,
      form: { name: '' }
    }
  },
  mounted() {
    // 监听滚动
    scrollEven((direct, removeScroll, event) => {
      this.removeHandleScroll = removeScroll
      this.handleScroll(direct, event)
    })
  },

  destroyed() {
    // 监听滚动
    this.removeHandleScroll()
  },
  methods: {
    // 滚动时关闭下拉框
    removeHandleScroll() {},
    handleScroll(direct, event) {
      if (!event.target.className.includes('el-select-dropdown__item')) {
        this.$refs.mySelect.blur()
      }
    }
  }
}
</script>

<style></style>

解决方案2. Vue监听Scroll事件

已使用该方案解决问题

1.gif

<template>
  <div>
    <el-button type="primary" @click="dialogVisible = true">Click</el-button>
    <el-dialog title="滚动表单" :visible.sync="dialogVisible" width="50%">
      <div ref="scrollDiv" style="height: 400px; overflow: auto">
        <el-form ref="form" :model="form" label-width="80px">
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-select ref="mySelect" v-model="form.name" placeholder="">
              <el-option
                v-for="item in 10"
                :key="item"
                :label="item"
                :value="item"
              >
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
        </el-form>
      </div>
      <div slot="footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false"
          >确 定</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dialogVisible: false,
      form: { name: '' }
    }
  },
  watch: {
    dialogVisible: {
      handler(val) {
       if (val) {
          this.$nextTick(() => {
            this.$refs.scrollDiv.addEventListener('scroll', this.ScrollChange, true);
          });
        } else {
          this.$refs.scrollDiv.removeEventListener('scroll', this.ScrollChange, true);
        }
      }
    }
  },
  mounted() {
  },
  methods: {
    ScrollChange(event) {
      console.log('event', event)
      this.$refs.mySelect && this.$refs.mySelect.blur()
    }
  }
}
</script>

解决方案3: 给滚动条所在的盒子加上Vue自定义指令

给父盒子绑定一个自定义指令directives, 根据类名获取到所有的下拉框, 监听内容区滚动时将打开的下拉框样式改成关闭

directives里包含三个钩子

  • bind:只调用一次,指令第一次绑定到元素时调用,进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用
  • update:所在组件的 VNode 更新时调用

3.1 步骤

  • 首先el-select标签要加上:popper-append-to-body='false' 下拉框默认是会插入body下面的,也就是不在咱们的弹窗中,如果不在弹窗中,根据类名获取父盒子下的元素,这一步就走不通了
  • 其次一定要找对父盒子,因为自定义是监听父盒子的滚动才会去处理关闭事件
  • 最后 把v-closeSelect加在对应父盒子标签上

1.gif

<template>
  <div>
    <el-button type="primary" @click="dialogVisible = true">Click</el-button>
    <el-dialog title="滚动表单" :visible.sync="dialogVisible" width="50%">
      <div v-closeSelect ref="scrollDiv" style="height: 400px; overflow: auto">
        <el-form ref="form" :model="form" label-width="80px">
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-select ref="mySelect" v-model="form.name" :popper-append-to-body="false">
              <el-option v-for="item in 10" :key="item" :label="item" :value="item"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item label="label">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
        </el-form>
      </div>
      <div slot="footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  directives: {
    closeSelect: {
      bind(el, binding, vnode) {
        //这里el是有滚动条的父盒子
        //获取盒子下所有下拉框
        let target = el.getElementsByClassName('el-select-dropdown');
        //处理方法 让所有下拉框隐藏
        el.handler = () => {
          for (let item of target) {
            console.log('item', item);
            item.style.display = 'none';
          }
        };
        //监听父子滚动
        el.addEventListener('scroll', el.handler);
      }
    }
  },
  data() {
    return {
      dialogVisible: false,
      form: { name: '' }
    };
  }
};
</script>
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务