页面滚动时隐藏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>
全部评论

相关推荐

有趣的牛油果开挂了:最近这个阶段收到些杂七杂八的短信是真的烦
点赞 评论 收藏
分享
诨号无敌鸭:恭喜佬,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务