
本文详解 Vue 3 中实现搜索框+下拉列表+多选功能的关键问题:解决因 @blur 导致无法点击选项的冲突,通过合理 DOM 包裹与事件委托确保下拉可见性与选项可选性,并正确将选中项(如水果名称)添加至响应式数组。
本文详解 vue 3 中实现搜索框+下拉列表+多选功能的关键问题:解决因 `@blur` 导致无法点击选项的冲突,通过合理 dom 包裹与事件委托确保下拉可见性与选项可选性,并正确将选中项(如水果名称)添加至响应式数组。
在 Vue 3 的搜索选择场景中,一个常见陷阱是:为隐藏下拉列表而对 绑定 @blur="optionsVisible = false",却导致点击下拉项时触发 blur(因为选项不在 input 内部),使下拉瞬间消失、点击失效。根本原因在于 blur 是焦点离开元素时触发,而下拉项是独立 DOM 节点,点击它们必然导致 input 失焦。
✅ 正确解法是:将 input 和下拉容器共同包裹在一个父级 以下是优化后的完整代码: ? 关键改进说明: ? 额外建议:<template><div false tabindex="0">
<input type="text" v-model="input" placeholder="Search fruits..." true><div class="item fruit" v-if="optionsVisible && filteredList().length" v-for="fruit in filteredList()" :key="fruit">
<p>{{ fruit }}</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8748" title="vue-composition-api-best-practices"><img
src="https://img.php.cn/upload/skill/000/000/081/179222222327548.jpg" alt="vue-composition-api-best-practices" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8748" title="vue-composition-api-best-practices" class="overflowclass">vue-composition-api-best-practices</a>
<p class="overflowclass">Vue 3 组合式 API 与 <script setup> 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8748" title="vue-composition-api-best-practices" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
</div>
<div class="item error" v-if="input && !filteredList().length">
<p>No results found!</p>
</div>
</div>
<div class="selected">Selected: {{ selected }}</div>
</template><script setup>
import { ref } from 'vue'
const input = ref('')
const optionsVisible = ref(false)
const selected = ref([])
const fruits = ['apple', 'banana', 'orange']
// ✅ 推荐:直接传入 fruit 值,避免依赖 DOM 操作
const select = (fruit) => {
if (!selected.value.includes(fruit)) {
selected.value.push(fruit)
}
input.value = '' // 可选:选中后清空搜索框
optionsVisible.value = false
}
// ✅ 支持回车快速选择首个匹配项
const handleEnter = () => {
const firstMatch = filteredList()[0]
if (firstMatch) {
select(firstMatch)
}
}
const filteredList = () => {
return fruits.filter(fruit =>
fruit.toLowerCase().includes(input.value.toLowerCase())
)
}
</script><style scoped>
.item.fruit p {
padding: 8px 12px;
cursor: pointer;
border-bottom: 1px solid #eee;
}
.item.fruit p:hover {
background-color: #f5f5f5;
}
.selected {
margin-top: 16px;
font-weight: 500;
}
</style>
若需支持多选不关闭下拉,可移除 optionsVisible.value = false 并添加「清除」按钮;若需高亮搜索关键词,可在 v-html 中动态插入 标签(注意 XSS 防护)。始终优先使用数据驱动而非 DOM 查询,让逻辑更清晰、更易维护。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










