当前位置: 首页 > news >正文

el-select下拉框,搜索时,若是匹配后的数据有且只有一条,则当失去焦点时,默认选中该条数据

1、使用指令

当所需功能只能通过直接的 DOM 操作来实现时,才应该使用自定义指令。可使用方法2封装成共用函数,但用指令他人复用时比较便捷。

        <el-table
          v-loading="tableLoading"
          border
          :data="tableList"
          default-expand-all
          row-key="id"
          :tree-props="{
            children: 'children',
          }"
        >
          <el-table-column
            align="center"
            label="下拉框"
            prop="selectProp"
          >
            <template #default="{ row }">
              <el-select
                v-model="row.selectProp"
                v-auto-select
                clearable
                filterable
                placeholder="请选择下拉框数据"
              >
                <el-option
                  v-for="item in select_data_source"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>
        </el-table>
<script setup>
import vAutoSelect from '@/directives/auto_select_directive'
</script>
//auto_select_directive.ts文件
import type { Directive } from 'vue'

interface ExtendedElement extends HTMLElement {
  _blurHandler?: (e: Event) => void
  _focusHandler?: (e: Event) => void
  _observer?: MutationObserver
  _currentDropdown?: HTMLElement | null
}

const vAutoSelect: Directive = {
  mounted(el: ExtendedElement) {
    const selectInput = el.querySelector('.el-input__inner')
    if (!selectInput) return

    // 精准定位当前下拉框
    const getCurrentDropdown = () => {
      const activePopper = document.querySelector(
        '.el-popper.el-select__popper[aria-hidden="false"]'
      ) as HTMLElement | null
      const selectWrapper = selectInput.closest('.el-select')
      if (activePopper && selectWrapper) {
        // 可以根据实际情况添加更多的判断条件,确保是当前 select 对应的下拉框
        return activePopper
      }
      return null
    }


    // 核心选择逻辑
    const autoSelectHandler = () => {
      const currentDropdown = getCurrentDropdown()
      if (!currentDropdown) {
        return
      }

      const visibleItems = currentDropdown.querySelectorAll<HTMLLIElement>(
        '.el-select-dropdown__item:not([style*="display: none"])'
      )

      if (visibleItems.length === 1) {
        visibleItems[0].click()
        const component = (el as any).__vueParentComponent?.ctx
        component?.handleClose?.()
      }
    }

    // 事件处理器
    const handleFocus = () => {
      el._currentDropdown = getCurrentDropdown()
    }


    const handleBlur = () => {
      autoSelectHandler()
    }


    // 智能监听器
    const initObserver = () => {
      //获取当前激活的下拉框元素
      const dropdown = getCurrentDropdown()
      if (dropdown) {
        // MutationObserver 是一个用于监听 DOM 变化的 API,它接受一个回调函数作为参数。它允许你异步地监听 DOM 的变动,如节点的添加、删除、属性的修改等,并在变动发生时执行相应的回调函数
        el._observer = new MutationObserver((mutations) => {
// mutations:一个包含所有变化记录(MutationRecord 对象)的数组。
          mutations.forEach((mutation) => {
            if (
              mutation.type === 'attributes' &&
              mutation.attributeName === 'style'
            ) {
              autoSelectHandler()
            }
          })
        })
        el._observer.observe(dropdown, {
          attributes: true, // 监听属性变化--布尔值,指示是否观察目标节点的属性变化
          attributeFilter: ['style'], // 只监听 'style' 属性的变化--字符串数组,指定要观察的属性名称
        })
      }
    }


    // 事件绑定
    selectInput.addEventListener('focus', handleFocus)
    selectInput.addEventListener('blur', handleBlur)
    el._focusHandler = handleFocus
    el._blurHandler = handleBlur

    // 初始化监听
    initObserver()
  },

  beforeUnmount(el: ExtendedElement) {
    // 清理事件
    const selectInput = el.querySelector('.el-input__inner')
    if (selectInput) {
      if (el._focusHandler) {
        selectInput.removeEventListener('focus', el._focusHandler)
      }
      if (el._blurHandler) {
        selectInput.removeEventListener('blur', el._blurHandler)
      }
    }

    // 清理 Observer
    el._observer?.disconnect()//调用 disconnect 方法可以停止观察,释放资源
    delete el._currentDropdown
  },
}

export default vAutoSelect

2、封装成共用函数

在输入文本进行搜索时,获取不到el-select内部匹配后的数据,故在失去焦点时,模拟搜索,获取筛选后的结果,当有且只有一条数据时,将那条数据赋给v-model绑定的值.

 <el-table
          v-loading="tableLoading"
          border
          :data="tableList"
          default-expand-all
          row-key="id"
          :tree-props="{
            children: 'children',
          }"
        >

          <el-table-column
            align="center"
            label="下拉框"
            prop="selectProp"
          >
            <template #default="{ row }">
              <el-select
                v-model="row.selectProp"
                clearable
                filterable
                placeholder="请选择下拉框数据"
                @blur="
                  (e) => {
                    selectSearchAuto(
                      e,
                      (newValue) => (row.selectProp= newValue),
                      select_data_source
                    )
                  }
                "
              >
                <el-option
                  v-for="item in select_data_source"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>
    </el-table>

<script setup>
  import { selectSearchAuto } from '@/utils'
</script>
//utils/index.ts文件
export function selectSearchAuto(
  event: { target: { value: string | undefined } },
  setValueCallback: (arg0: any) => void,
  dataList: any[]
) {
  const query = event.target.value?.trim()
  if (!query) return
  const filteredOptions = dataList.filter((item) => item.label.includes(query))
  if (filteredOptions.length === 1) {
    setValueCallback(filteredOptions[0].value)
  }
}

使用成本相对较高

相关文章:

  • Vue2与Vue3中TS子组件传值给父组件
  • Chair Assembly Process
  • 服务器入门笔记
  • 2.5 微分
  • Apache Dubbo Pixiu打造微服务生态的轻量级 API 网关
  • 【测试工具】如何使用 burp pro 自定义一个拦截器插件
  • 3.23-libevent
  • Android Studio常见问题解决
  • 2024年认证杯SPSSPRO杯数学建模C题(第二阶段)云中的海盐全过程文档及程序
  • HTML云原生:概念、技术与应用的全面解析
  • STM32学习笔记之keil使用记录
  • 模式搜索+扩散模型:FlowMo重构图像Token化的技术革命
  • 2025年河北省第二届职业技能大赛网络安全项目 模块 B样题任务书
  • 运动仿真——phased.Platform
  • StarRocks vs Doris:深度剖析与选型分析
  • DeepSeek底层揭秘——EPLB
  • llama源码学习·model.py[5]FeedForward前馈神经网络
  • PyTorch生成式人工智能实战:从零打造创意引擎
  • 华为OD机试2025A卷 - 构成正方形的数量(Java Python JS C++ C )
  • dsPIC33CK64MC105 Curiosity Nano|为高性能数字电源与电机控制而生
  • 航海王亚洲巡展、工厂店直销……上海多区推出“五五购物节”活动
  • 五大国货美妆去年业绩分化:珀莱雅百亿营收领跑,上海家化转亏
  • 水利部将联合最高检开展黄河流域水生态保护专项行动
  • 赵乐际主持十四届全国人大常委会第十五次会议闭幕会并作讲话
  • 神十九乘组安全顺利出舱
  • 4月译著联合书单|心爱之物:热爱如何联结并塑造我们