☰
el-select回车不收起下拉菜单?从键盘交互到自定义事件的完整解决方案
2026/10/15 17:57:15 网站建设 项目流程

1. 先弄明白el-select的键盘交互机制:为什么回车不会收起下拉框

做后台管理系统的时候,很多同事都跟我抱怨过同一个问题:在el-select里用键盘选完值,习惯性地按一下回车,结果发现下拉面板纹丝不动地挂着,要么就自己从"选中状态"又弹出来了,表单怎么都提交不上去。

一开始我也以为是ElementUI的bug,后来翻了几遍源码,才意识到这根本不是缺陷,而是组件的交互模型和我们日常的"回车即确认"直觉有冲突。理解了这个模型,后面所有的"隐藏下拉菜单""触发键盘事件"就都有了解法。

1.1 下拉面板的显示状态:组件内部的visibleState到底由谁控制

el-select组件内部维护了一个叫visibleState的布尔值,它决定了下拉面板是否渲染、是否展开。这个值不是只受点击影响的,它同时被以下几种信号驱动:

  • 鼠标点击输入框/触发器时置为true,点击外部区域、选择完选项时会被置回false,这是最常见的方式。
  • 键盘操作时,visibleState会被独立处理。具体来说,在组件根节点上绑定了keydown事件,当按下Enter时,组件内部逻辑首先是"让当前高亮项生效",而不是切换面板开合状态。
  • visibleState还受disabled、远程搜索的loading、filterable清空状态影响,某些状态下即使你调用了显示方法,面板也会被强制收起。

我用一个通俗类比来解释:el-select把"回车"和"点击"这两个动作绑定到了同一个回调上。你点鼠标时,点击事件天然会触发失焦(blur),blur又会把面板关掉,所以看起来"点击一下就把面板关了";但回车不会让输入框失焦,所以组件认为你还在面板里继续操作,自然不会主动关。

这就是为什么你按回车想"确认并提交",但面板仍然赖着不走。

1.2 回车键在组件内部的实际处理链路:从keydown到option的click

要解决"回车隐藏下拉菜单"的问题,必须先搞清楚el-select里回车键被分发到了哪里。

在ElementUI 2.x版本的源码中,el-select根节点上绑定了keydown事件处理函数,在这个处理函数内部有一个非常关键的switch判断:

// 简化自 ElementUI 内部逻辑 handleKeydown(event) { const { keyCode } = event; // 删除、方向键对 highlightOption 进行上下移动 if (keyCode === 38 || keyCode === 40) { this.highlightOption(event); return; } // Enter 键:触发已选中(高亮)选项的点击逻辑 if (keyCode === 13) { if (this.visibleState && this.highlightIndex >= 0) { this.options[this.highlightIndex].click(); event.preventDefault(); } } }

说几个容易被忽略的细节:

  • options[this.highlightIndex].click()并不是原生DOM的click,而是组件内部封装的方法,它会触发一次"当前项被选中"的动作。
  • 这个动作最终会调用handleOptionSelect,把选中值写进绑定的v-model,然后大多数情况下会收起面板——注意,是大多数情况。你如果设置了multiple多选模式,回车选择完一项时面板不会关闭,这是刻意设计,方便连续选择多项。
  • 如果你的下拉选项中某个option设置了disabled,回车作用在它上面时不会触发任何关闭逻辑,你会觉得"回车键失灵了"。
  • 如果当前没有高亮项(highlightIndex === -1),回车按键会被组件吞掉,既不会触发选中,也不会收起面板,也不会向上冒泡到你的业务代码里。

明白了这个链路,你就该知道:让回车隐藏下拉菜单,本质上是要抢在组件内部逻辑之前处理回车事件,或者在组件选中动作完成之后主动去收面板。

2. 让回车真正"听话":隐藏下拉菜单的几种可行路径

针对"回车时隐藏下拉菜单"这个诉求,我试过好几种方案,有简单粗暴的,也有相对优雅的。先给结论:没有一种方案是银弹,取决于你的业务场景是"回车提交表单"还是"回车仅确认选择"。下面把我验证过的路径列出来,并标注适用场景。

2.1 方案一:手动触发blur事件——最自然但最容易翻车

原理很简单:el-select在失去焦点时会自动把visibleState置为false,所以只要你能让输入框主动失焦,面板就收了。

<el-select ref="mySelect" v-model="value" @keydown.enter.native="handleEnter" > <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select>
handleEnter() { // 基于常见实践的补充:利用原生 DOM 能力触发放弃焦点 this.$refs.mySelect.$refs.input.blur(); // 后续处理你自己的键盘事件,比如提交表单 this.confirmByEnter(); }

这个方案在单选、非filterable场景下实测是有效的——$refs.input指向组件内部的input元素,对它调用blur()会导致整个select组件失焦,进而收起面板。

但这方案有几个坑,我逐一说明:

  • 如果你用的是filterable可搜索模式,$refs.input是你的搜索输入框。回车之后你虽然调用了blur,但搜索框在失焦瞬间可能触发@blur事件,此时如果下拉列表还有残余文本,会先触发清空逻辑,导致你刚选中的值看起来"被清掉了"。实际测下来不是值被清掉,而是显示名来回闪了一下,体验很差。
  • 如果你是这个select的唯一下拉组件,直接blur没什么问题;但如果页面里有其他逻辑依赖这个select的focus状态(比如根据焦点显示联动信息),blur会误触联动逻辑。
  • 某些内部版本ElementUI中,this.$refs.mySelect.$refs.input可能不是输入框而是触发器元素,直接调用blur()会报错。稳妥的做法是先判断$refs.input && $refs.input.blur类型。

所以我现在的习惯是:blur()方案只用于最简单、单一、无搜索框的select场景。

2.2 方案二:间接驱动visibleState——更可控但不推荐直接操作内部状态

既然visibleState决定面板开合,那能不能直接改组件的visibleState?能,但不建议。原因是ElementUI的组件状态更新并不是所有字段都能响应式驱动UI,直接改visible相关内部数据,在2.15.x版本里确实有效,但依赖内部命名属于"贴地飞行",升级小版本有可能失效。

一个更可控的间接做法是:通过调用组件暴露的focus方法、再立刻触发别的操作,让组件以为自己失焦。这个方法比较绕,实现如下:

handleEnter() { const select = this.$refs.mySelect; // 重点:先让组件重新聚焦,再在下一帧强制让它失焦,达到“收起但不改变选中值”的效果 if (select.focused) { select.$refs.input.blur(); } // 你的业务逻辑 this.confirmByEnter(); }

这种做法的本质还是借用blur,只是加了一层"确保当前处于聚焦态"的判断,避免重复调用blur引发的异常。

真正能精准控制面板开合的,是在模板上绑定的visible属性,注意这个visible是ElementUI 2.15+版本中el-select支持的一个属性,用于手动控制下拉面板的显示隐藏:

<el-select v-model="value" :visible="dropdownVisible" @keydown.enter.native="handleEnter" @visible-change="(val) => dropdownVisible = val" >
handleEnter() { // 基于常见实践的补充:面板展开时,先主动将 visible 置为 false,再执行业务逻辑 this.dropdownVisible = false; this.confirmByEnter(); }

这是个非常干净的方案,适合新版ElementUI。但有个前提:visible属性第一次生效需要组件完成初始化,如果你在组件mounted之前就设置了true,会出现面板初始状态异常的情况。另外,当你写:visible时,组件内部会认为面板的开关完全由外部控制,这时鼠标点击输入框将不再自动展开面板——你必须在点击事件里自己设置dropdownVisible = true。等于把开关逻辑全接管过来了,工作量反而变大了。

2.3 方案三:模拟点击触发器——最接近用户手动操作的"伪装"方案

这个方法是从一个老前端同事那学来的:el-select的触发逻辑本质上绑在"点击"事件上,如果能让组件内部"认为"自己经历了点击+失焦,面板自然就收起了。实现方式是在回车事件里依次触发$refs.select.handleBlur()或者触发触发器元素的click再blur。但我实测之后认为这个方案太依赖组件内部方法,不推荐在新的代码里使用,因为组件内部方法名在压缩混淆后不稳定。

综上,我把目前可用的方案整理成表格,方便你对照选型:

方案实现难度适用范围稳定性额外注意点
手动blur低单选、无filterable的简单表单场景中对搜索/清空逻辑有干扰
外部visible控制中新版ElementUI(2.15+)高必须接管点击展开逻辑
模拟触发器点击中老项目临时救急低依赖内部方法名,不推荐
监听键盘并回调业务函数低所有场景高需要配合上面任一种收面板方案

3. 回车触发自定义键盘事件的完整实现:带可复现的代码样例

方案确认之后,最核心的问题就变成了:在收面板的同时,怎么触发属于你自己的键盘事件逻辑。比如回车确认提交、回车跳转下一步、回车搜索等。

这一节我直接给出一份可复现代码,并解释每段代码的设计意图。

3.1 场景设定与代码结构

假设这样一个业务场景:某个订单编辑页面里,用户可以从下拉框选择"配送方式",选完后必须按回车确认,系统自动把确认结果提交到服务端,同时关闭下拉面板。

为了避免冲突,我把"组件自身的回车选中行为"和"业务确认行为"彻底分开:

<template> <el-select ref="deliverySelect" v-model="deliveryType" class="delivery-select" :filterable="false" @keydown.enter.native.prevent="handleDeliveryEnter" @change="handleDeliveryChange" @visible-change="handleVisibleChange" > <el-option v-for="item in deliveryOptions" :key="item.type" :label="item.label" :value="item.type" /> </el-select> </template>

这里有个常被忽略的关键点:@keydown.enter.native.prevent。由于el-select是组件,普通的@keydown.enter并不会绑定到原生DOM上,必须加.native修饰符才能监听到。同时加.prevent的作用是阻止事件继续传递给组件内部的keydown处理逻辑——这一步是重中之重,如果不阻止默认行为,组件内部会在按下回车时执行"高亮项选中"而非你的业务逻辑。

3.2 业务处理函数:收面板 + 取当前高亮项 + 触发确认事件

data() { return { deliveryType: '', deliveryOptions: [ { type: 'express', label: '快递配送' }, { type: 'self_pick', label: '门店自提' }, { type: 'same_city', label: '同城急送' } ], currentHighlightIndex: -1, panelOpened: false }; }, methods: { // 回车主处理逻辑 handleDeliveryEnter(event) { // 1. 收起面板——手动blur方案(此处适用于无filterable的单选) this.$refs.deliverySelect.$refs.input.blur(); // 2. 触发键盘事件后续业务逻辑 // 这里根据组件当前选中值和面板状态决定行为 if (this.panelOpened) { this.confirmByEnter(); } else { // 面板本身就是关闭状态,说明用户把select当成一次性提交按钮 this.submitAfterEnter(); } }, // 业务确认逻辑 confirmByEnter() { // 业务侧操作,例如提交表单或者查询列表 console.log('回车确认,当前值:', this.deliveryType); this.submitDelivery(this.deliveryType); }, submitAfterEnter() { console.log('面板未打开,直接提交'); this.submitDelivery(this.deliveryType); }, submitDelivery(type) { // 模拟提交:实际项目里这里会调用API this.$message.success(`已确认配送方式:${type}`); }, handleDeliveryChange(val) { // 值变化时,如果面板还开着,按回车应该要触发confirm console.log('选中值变化为:', val); }, handleVisibleChange(val) { this.panelOpened = val; } }

3.3 为什么这个实现能同时满足"隐藏菜单"和"触发键盘事件"

这段代码的核心有两点:

第一,用@keydown.enter.native.prevent把回车事件从组件内部逻辑里"抢"了过来。因为.prevent会调用event.preventDefault(),组件内部监听到的回车事件虽然也触发了,但不会执行options[highlightIndex].click()。此时组件的选中状态不会被改变,面板也不会自己关闭。

第二,主动调用blur()来触发组件自身的失焦收起机制。这一步等于把"回车确认"和"点击外部区域关面板"两种路径统一了。面板收起后,组件触发visible-change事件,handleVisibleChange会把panelOpened置为false,进而后续的键盘事件逻辑可以依据这个状态做分支。

你可以把整个流程想象成:你自己按下了一个"组合开关"——先关掉组件默认的回车行为,再触发组件的失焦行为,最后执行自己的业务回调。三件事互相隔离但又顺序清晰。

3.4 如果你必须支持多选模式,代码要改哪里

多选模式(multiple)下直接blur会导致已选中的tag被意外收起,而且多选状态下回车选中当前项后组件本来就不关闭面板,这是为了方便连续选择。如果你希望多选状态下回车确认并关闭:

handleDeliveryEnter(event) { // 多选场景:阻止默认行为,强制关闭面板,但不影响已选中的tags event.preventDefault(); // 多选时 $refs.input 可能不指向真实输入框,所以更稳妥的是调用 select 身上的 visible 控制 this.$refs.deliverySelect.visible = false; // 基于常见实践的补充,不推荐直接改内部属性,仅供参考 // 业务逻辑照常 this.confirmByEnter(); }

但多选场景下我更建议使用外部控制visible方案,因为多选tag的显示是独立的,面板关闭不关闭和选中值没有必然联系,外部控制更清晰。下面会讲。

4. 实测中容易踩的四个坑:enter被吞、高亮丢失、异步选项、面板不收起

真实项目里,很少有一上来就顺顺利利跑通的场景。我列几个自己踩过、也帮同事排查过的典型问题,每个都给出完整的定位链路和解决方案,方便你对号入座。

4.1 坑一:回车事件被组件"吞"了,业务代码根本没执行

现象:绑定了@keydown.enter.native,但回调不触发;面板倒是自己收了,业务逻辑一点反应都没有。

定位过程:

  • 我先在回调里加了console.log,确认没打印。
  • 然后检查是不是被@keydown.enter(没有.native)绑定了——这是最容易被忽视的,el-select本身不是原生input,不加.native时Vue会把事件当成组件自定义事件,而组件内部并没有keydown-enter这种事件定义,所以回调永远不触发。
  • 改成.native后回调触发了,但执行得太晚——组件内部先一步处理了回车并选中了当前项,再轮到我们的回调时,面板状态已经变了。

解决方案:

<!-- 正确的写法:.prevent 优先阻断组件的内部行为 --> <el-select @keydown.enter.native.prevent="handleEnter">

如果你既想触发自己的逻辑,又希望选中当前高亮项(即"回车既选中又确认"),就不能用.prevent,而应该去掉.prevent,改成在@change里做确认逻辑:

<el-select @keydown.enter.native="handleEnter" @change="handleChange">

这种情况下组件内部会把高亮项选中并触发change,你在handleChange里确认选中即可,而handleEnter里只负责关闭面板。

定位这类问题最有效的方式是:在浏览器控制台里给el-select组件实例打console.log(this.$refs.mySelect),把$listeners、$attrs展开看看事件有没有被正确绑定。如果是$listeners里没有keydown,说明绑定方式不对;如果keydown在但回调不触发,说明事件被内部逻辑拦截了。

4.2 坑二:回车时设置了不存在的"当前高亮项"导致选择无效

现象:下拉面板打开,键盘上下选择项,高亮状态看起来移动到了某个选项上,但一回车,选中的却是上一次的值,而不是当前高亮的值。

定位过程:

  • 检查highlightIndex的值,发现它没跟随鼠标hover更新。
  • 再看组件的@mouseenter事件,发现选项上的hover事件并未触发,因为el-option组件在鼠标enter时是通过hoverIndex来记录的,但当鼠标在某个选项上时,键盘的上下键操作不会重置hoverIndex,这就导致键盘高亮(highlightIndex)和鼠标悬停(hoverIndex)两个状态互相干扰。
  • 回车的选中逻辑是基于hoverIndex还是highlightIndex?实测结论:ElementUI 2.x中,组件优先使用highlightIndex,但如果highlightIndex为-1而hoverIndex有值时,click()动作会作用在hoverIndex对应的选项上。所以当你键盘上下选择时,highlightIndex更新了,但hoverIndex还停留在鼠标最后停留的位置上,如果回车时组件内部取的是hoverIndex,就会导致"选中了鼠标悬停项而不是键盘高亮项"。

这个坑多发生在鼠标和键盘混用的操作场景下。解决办法有两个:

  • 在@keydown.enter.native回调里,手动根据方向键状态设置hoverIndex = highlightIndex,但因为是组件内部数据,操作起来并不优雅。
  • 更推荐的做法:直接放弃组件默认回车选中逻辑,用@change来同步高亮项和选中项,自己维护键盘导航。这相当于把键盘行为从组件内部"接管"出来。

我实际采用的折中方案是:监听方向键事件,在按下方向键后主动把鼠标hover状态清除:

handleKeydownNav(event) { if (event.keyCode === 38 || event.keyCode === 40) { // 键盘操作时清除鼠标hover影响,避免回车选中错位 this.$refs.deliverySelect.hoverIndex = -1; } }

这个方案虽然依赖内部字段,但在2.x版本中已经稳定运行很长时间。

4.3 坑三:远程搜索 + 异步选项时,回车收面板后选中的值丢失

现象:使用filterable+remote远程搜索时,回车确认后下拉面板收起,但输入框显示的值和v-model不一致,或者重新打开面板时选中项消失了。

定位过程:

  • 查看网络请求日志,发现回车确认后,远程搜索接口还在等待响应。
  • 此时v-model已经更新为回车选中的值,但由于搜索关键字还停留在输入框里,组件内部的selectedLabel会先显示关键字而不是选中项的名称。
  • 我手动blur收面板时,搜索框会触发清空逻辑,但此时远程搜索的结果还没返回,组件认为当前没有匹配项,就把选中的标签重置了。

解决方案是:在远程搜索场景下,不要依赖blur来收面板。改用外部控制visible的方案,并且在visible-change回调里延迟清空搜索关键字:

handleVisibleChange(val) { if (!val) { // 基于常见实践的补充:延迟清理搜索关键字,等待远程数据返回后再重置 setTimeout(() => { this.$refs.deliverySelect.query = ''; }, 100); } }

query是el-select组件内部用来存储搜索关键字的字段,你也可以用官方文档里的filter-method配合自定义状态来管理搜索词。

4.4 坑四:面板是否收起的效果在你自己的DOM里看不出来

现象:代码逻辑看着没问题,blur()也调了,但页面上面板并没有收起来。而且只在部分浏览器(旧版Edge、某些内嵌WebView)里这样。

定位过程:

  • 检查浏览器控制台报错,确认$refs.input存在,调用没报错。
  • 发现这些浏览器中,blur()是同步执行的,但组件内部的visibleState更新是异步的($nextTick之后)。如果在同一个事件循环里马上又让组件重新获得焦点(比如回车后自动聚焦到下一个输入框),focus事件会先把visibleState置为true,然后又因为blur置为false,最终两个异步操作叠加,状态冲突导致面板卡在打开状态。
  • 进一步测试,在回车事件里调用event.preventDefault()之后,如果后面紧接着同步调用了this.$nextTick(() => ...)重新聚焦,才会稳定复现。

解决方案是在blur和后续聚焦之间加一个微任务间隔,让组件内部的visibleState先稳定到关闭状态:

handleEnter() { this.$refs.deliverySelect.$refs.input.blur(); // 在下一帧重新聚焦到目标元素,避免blur和focus在同一个事件循环里打架 this.$nextTick(() => { this.$refs.targetInput.focus(); }); this.confirmByEnter(); }

这个坑其实反映了所有异步UI组件的通性:手动调用组件暴露的方法时,要给它一个状态稳定窗口,不要在同一事件循环里连续做两个互斥的UI操作。这个经验在Vue里对其他组件也适用,比如el-popover、el-tooltip的显示切换,都有类似的异步状态更新逻辑。

5. 从ElementUI到Element Plus:回车行为的差异与适配

如果你维护的项目正在从Vue2 + ElementUI迁移到Vue3 + Element Plus,回车处理这块有几个差异值得提前注意。我有一次迁移后才发现,原本跑得好好的回车逻辑在Element Plus里完全失效了,最后定位到的原因是组件内部命名和事件分发机制都变了。

5.1 Element Plus的回车处理:toggleMenu触发源变更

Element Plus重写了下拉组件的键盘控制逻辑,不再优先走options[highlightIndex].click()这条路。在Element Plus中,回车键的逻辑是先检查当前是否有高亮项,如果高亮则触发selectOption,否则把toggleMenu置为false,从而只关闭面板而不做选择。

这个差异带来两个直接影响:

  • 原来在ElementUI里"回车选中但面板不关"的行为,在Element Plus里变成了"回车选中并主动关面板"。如果你的业务代码在ElementUI里靠手动blur关面板,迁移后会出现重复关闭,一般不会报错但会触发额外的visible-change事件,导致一些监听逻辑重复执行。
  • Element Plus中$refs.select.$refs.input不再是输入框实例,而是整个组件根节点。直接调用blur()不会有任何作用,因为新的根节点不是focusable的节点。

如果你在做适配,建议把收面板逻辑统一从"手动blur"改成"外部visible属性控制",这样在Element Plus上能继续正常工作,而且Element Plus对visible属性的定义更加明确。

5.2 同一套逻辑在Element Plus下的改造示例

<el-select ref="deliverySelect" v-model="deliveryType" :visible="dropdownVisible" @keydown.enter.prevent="handleDeliveryEnter" @visible-change="handleVisibleChange" >
data() { return { dropdownVisible: false, }; }, methods: { handleDeliveryEnter() { // Element Plus:直接控制visible,不再操作blur this.dropdownVisible = false; this.confirmByEnter(); }, handleVisibleChange(val) { this.dropdownVisible = val; }, toggleDropdown() { // 接管自动展开:点击输入框区域时手动打开 this.dropdownVisible = !this.dropdownVisible; } }

同时在模板里给输入框区域加一个点击事件绑定toggleDropdown,否则用户无法通过鼠标展开面板。

5.3 迁移时的回归测试清单

如果你准备把项目迁移到Element Plus,以下几条建议直接保存下来,回头逐项验证:

  • 键盘上下选择时,高亮项是否正常移动。
  • 远程搜索时,回车确认后是否出现值丢失。
  • 多选模式下回车是否会误关面板。
  • visible属性外置后,鼠标点击其他区域是否还能正常关闭面板。
  • 表单提交时按回车是否会错误地触发下拉面板的打开逻辑。

另外,Element Plus对键盘事件使用了Vue3的onKeydown绑定方式,如果你在模板中同时使用了.native修饰符,Vue3会直接编译报错。所有原来写了.native的键盘绑定都需要去掉,改成普通的@keydown,因为组件事件和原生事件在Vue3中的区别已经没以前那么大了。

6. 一个更通用的思路:自己封装一个"回车确认下拉选择框"

经历了几次踩坑后,我现在遇到类似需求,通常不只是改el-select的用法,而是直接把它的键盘行为封装成一个自定义组件。这样既能把"回车确认"这种业务语义固化下来,又能在未来迁移到别的组件库时少改很多调用方代码。

6.1 封装思路与API设计

我给这个封装取名"确认型选择框",对外暴露的核心接口很简单:

  • value:双向绑定值
  • options:选项列表
  • @confirm:回车确认事件
  • @change:选中变化事件

组件内部做的事情只有三件:

  1. 在@keydown.enter.prevent里阻止默认行为;
  2. 关闭自身下拉面板;
  3. 触发confirm事件并把当前选中的值一并传出去。

这个封装最大的价值在于:你把"回车是否允许改变选中值"这个策略决定权升到了父组件层级。以后不管底层组件库怎么改键盘行为,你只维护这一个封装内部逻辑,业务侧完全察觉不到。

6.2 代码示例(基于ElementUI 2.x)

<template> <el-select :value="value" :visible="visible" @input="handleInput" @visible-change="handleVisibleChange" @keydown.enter.native.prevent="handleEnter" @click.stop="toggleVisible" > <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </template>
export default { name: 'ConfirmSelect', props: { value: { type: [String, Number], default: undefined }, options: { type: Array, default: () => [] } }, data() { return { visible: false }; }, methods: { handleInput(val) { this.$emit('input', val); }, handleVisibleChange(val) { this.visible = val; }, toggleVisible() { this.visible = !this.visible; }, handleEnter() { // 关闭面板 this.visible = false; // 触发业务确认事件 this.$emit('confirm', this.value); } } };

实际使用时,页面里写起来非常简洁:

<confirm-select v-model="deliveryType" :options="deliveryOptions" @confirm="confirmHandler" @change="valueChangedHandler" />

6.3 封装后的几个好处

封装之后,我在新项目里几乎不用再直接操作el-select的内部状态。原来那些手动blur、修改hoverIndex、控制query的代码全部收拢进了一个地方,各业务组件里只体现业务意图。而且这个封装对后续技术栈升级的影响面也最小——就算ElementUI换成了别的组件库,我只改封装内部,所有调用方照常运。

如果你也经常在项目里跟表单打交道,我个人建议尽早把这种"带确认语义"的通用交互组件沉淀下来,无论是不是用el-select,这种套路在Ant Design Vue的a-select、小程序的picker组件上同样适用。交互逻辑的抽象能力,才是这次踩坑经历换来的最大收获。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询