Skip to content
广告位招租

优质广告位诚邀合作

本广告位曝光量正火速攀升,用户触达规模呈爆发式增长!现向品牌开放合作,趁曝光增长红利期,抓紧机会拿下,让您的品牌借势破圈!

--总浏览量(次)
--总计访客(人)

close dropdown

自定义指令之v-close-dropdown,该指令用于在滚动时自动关闭 Element Plus 的下拉弹出框(Select、Cascader、DatePicker、ColorPicker),支持配置滚动监听目标和触发距离阈值。

适用场景

当页面或容器中存在 Element Plus 的下拉组件(如 el-selectel-cascaderel-date-pickerel-color-picker),用户滚动时弹出框不会自动收起,导致弹出框悬浮在页面中。本指令通过监听滚动事件,自动关闭这些弹出框。

支持关闭的弹出框

组件弹出框选择器
el-select.el-select__popper
el-cascader.el-cascader__dropdown
el-date-picker / el-time-picker.el-picker__popper
el-color-picker.el-color-dropdown

指令值格式

v-close-dropdown 接受三种类型的绑定值:

1. 布尔值

说明
true监听 window 滚动(默认)
false监听元素自身滚动
vue
<!-- 监听 window 滚动 -->
<div v-close-dropdown="true">

<!-- 监听元素自身滚动 -->
<div v-close-dropdown="false" style="overflow: auto; max-height: 400px">

2. 对象

属性类型默认值说明
windowbooleantruetrue 监听 window 滚动,false 监听元素自身滚动
distancenumber50触发关闭所需的滚动距离阈值(px)。0 表示滚动即触发
classNameList`stringArray`[".el-popper"]默认值永远都在,不会覆盖
vue
<!-- 监听元素自身滚动,滚动超过 100px 才触发关闭 -->
<div
  v-close-dropdown="{ window: false, distance: 100 }"
  style="overflow: auto; max-height: 400px"
>

3. 数字

直接指定滚动距离阈值(px),默认监听 window 滚动。

vue
<!-- 监听 window 滚动,滚动超过 200px 才触发关闭 -->
<div v-close-dropdown="200">

4. 数组

直接指定classNameList

vue
<!-- 监听 window 滚动,滚动超过 200px 才触发关闭 -->
<div v-close-dropdown="['.el-popper','xiaobu-popper']">

绑定值对照表

绑定值滚动目标距离阈值
truewindow50(滚动50像素触发)
false元素自身50(滚动50像素触发)
{ window: true }window50
{ window: false }元素自身50
{ window: false, distance: 100 }元素自身100px
200window200px

使用示例

全局注册

ts
import closeDropdown from "@/directives/closeDropdown"

app.use(closeDropdown)

场景一:整页滚动关闭

页面整体滚动时关闭所有弹出框:

vue
<template>
  <div v-close-dropdown="true">
    <el-select v-model="value" placeholder="选择">
      <el-option label="选项一" value="1" />
      <el-option label="选项二" value="2" />
    </el-select>

    <el-date-picker v-model="date" type="date" placeholder="选择日期" />

    <!-- 大量内容,使页面可滚动 -->
    <div v-for="i in 100" :key="i">内容行 {{ i }}</div>
  </div>
</template>

场景二:局部容器滚动关闭

表格区域滚动时关闭弹出框:

vue
<template>
  <div v-close-dropdown="{ window: false, distance: 50 }" class="table-container">
    <el-table :data="tableData" height="400">
      <el-table-column prop="name" label="名称">
        <template #default="{ row }">
          <el-select v-model="row.status">
            <el-option label="启用" value="active" />
            <el-option label="禁用" value="inactive" />
          </el-select>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<style scoped>
.table-container {
  overflow: auto;
}
</style>

场景三:带距离阈值

避免轻微滚动就关闭弹出框,提升用户体验:

vue
<template>
  <!-- 滚动超过 100px 才关闭弹出框 -->
  <div v-close-dropdown="100">
    <el-cascader v-model="cascaderValue" :options="options" />
    <div v-for="i in 200" :key="i">内容行 {{ i }}</div>
  </div>
</template>

工作原理

用户滚动

  ├─ 累计滚动距离 < distance?
  │    └─ 是 → 不触发,继续监听

  └─ 累计滚动距离 ≥ distance?
       └─ 是 → 标记已触发

            ├─ 1. 向 document.body 派发模拟点击事件
            │     (pointerdown → mousedown → mouseup → click)
            │     → 触发 Element Plus 内部的关闭逻辑

            └─ 2. 兜底:直接隐藏可见的弹出框 DOM
                  (设置 display: none)
  • 防抖处理:关闭操作使用 99ms 防抖(首尾均触发),避免滚动过程中频繁执行。
  • 状态重置:滚动停止 101ms 后重置触发状态,下次滚动需重新达到阈值才会触发。
  • 智能跳过:如果滚动停止后弹出框仍处于打开状态且未被关闭过,则不重置滚动基准位置,避免误判。

注意事项

  1. 依赖 Element Plus:本指令针对 Element Plus 的弹出框选择器编写,不适用于其他 UI 库。
  2. 弹出框选择器:如 Element Plus 版本更新导致弹出框类名变更,需同步更新指令内的选择器。
  3. distance 为 0 时:任何滚动都会立即触发关闭,适用于大多数场景。
  4. distance 大于 0 时:仅当累计滚动距离超过阈值后才触发,适合需要精确操作弹出框的场景。
  5. 模拟点击事件:指令通过向 document.body 派发坐标为 (0, 0) 的模拟点击事件来关闭弹出框,不会影响其他正常交互。

微信公众号【爆米花小布】

0%

置顶

置顶