Vue问题:如何让点击事件在blur监听触发前设置数据
自定义下拉组件点击事件触发问题解决
问题背景
我正在开发一个带动态过滤功能的自定义下拉组件,需要实现以下效果:
- 点击输入框时,下拉列表显示(绑定
@focus事件) - 离开输入框时,下拉列表隐藏(绑定
@blur事件) - 点击列表项时,把输入框的
liveSearch值设为选中的项
目前前两个功能正常,但点击列表项时,输入框的blur事件会抢先触发,下拉框直接隐藏,导致赋值操作没来得及执行。试过把isDropdownOpen改成切换函数,但下拉的显示/隐藏功能直接失效了。
问题原因
事件触发顺序导致的:点击列表项时,输入框的blur事件会先于列表项的click事件执行,下拉框提前隐藏后,click事件的逻辑就无法正常完成。
解决方案
方法一:用mousedown替代click
mousedown事件的触发时机早于blur,能保证赋值逻辑先执行。同时阻止<a>标签的默认跳转行为:
修改列表项的事件绑定:
<a href="#" class="dropdown-item" v-for="item in queryKeyFilter" @mousedown.prevent="setQuery(item)"> {{ item }} </a>
还可以在setQuery方法里手动隐藏下拉框,体验更流畅:
setQuery(item) { this.liveSearch = item; this.isDropdownOpen = false; // 赋值完成后手动关闭下拉 }
方法二:延迟blur事件的执行
给blur事件的处理逻辑加一个短暂延迟,让click事件有足够时间执行:
<input @focus="isDropdownOpen = true" @blur="() => setTimeout(() => isDropdownOpen = false, 100)" type="text" class="form-control" placeholder="Search..." v-model="liveSearch" />
完整代码示例(方法一)
new Vue({ el: "#app", data: { isDropdownOpen: false, liveSearch: '', queryKeyFilter: ['Item 1', 'Item 2', 'Item 3'] }, methods: { setQuery(item) { this.liveSearch = item; this.isDropdownOpen = false; } } });
.scrollable-menu { height: 150px; overflow-y: auto; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <div id="app"> <div class="input-group mb-3"> <input @focus="isDropdownOpen = true" @blur="isDropdownOpen = false" type="text" class="form-control" placeholder="Search..." v-model="liveSearch" /> </div> <div class="dropdown-menu" :class="{ show: isDropdownOpen }"> <div class="scrollable-menu"> <a href="#" class="dropdown-item" v-for="item in queryKeyFilter" @mousedown.prevent="setQuery(item)"> {{ item }} </a> </div> </div> </div>
内容的提问来源于stack exchange,提问作者Yolo_chicken
相关产品推荐
相关产品推荐

