js 下拉菜單點(diǎn)擊旁邊收起實(shí)現(xiàn)(踩坑記)
背景:
最近在搞一個(gè)需求:搜索框,輸入時(shí)顯示聯(lián)想詞下拉列表,當(dāng)點(diǎn)擊聯(lián)想詞跳轉(zhuǎn)到搜索頁(yè),如果點(diǎn)擊其他部分收起聯(lián)想的下拉列表。接到需求后第一反應(yīng)用失焦(blur)去做收起操作避免body的監(jiān)控,隨后就踩坑里了,下面情景再現(xiàn),一步一步來看這個(gè)問題的解決(里面的demo等會(huì)用vue實(shí)現(xiàn))
帶有bug的版本演示圖

備注:最后的搜索跳轉(zhuǎn)我直接用console代替掉了,但是并沒有執(zhí)行
問題拋出
當(dāng)我點(diǎn)擊上面的聯(lián)想詞的時(shí)候它的onSearch并不能執(zhí)行
demo代碼展示
<template lang="html">
<div :class="[baseClass + '-wrap']">
<input
type="text"
v-model="searchVal"
:class="[baseClass + '-input']"
ref="demo-search-input"
placeholder="搜索"
@focus="onFoucs"
@blur="onBlur"
@keyup.enter="onSearch"
@input="getRecommendedList" />
<span :class="[baseClass + '-btn']" @click="onSearch"></span>
<div :class="[baseClass + '-recommended']" v-show="isShowRecommend && recommendList.length > 0">
<div :class="[baseClass + '-triangle-border', baseClass + '-tb-border']"></div>
<div :class="[baseClass + '-triangle-border', baseClass + '-tb-bg']"></div>
<ul :class="[baseClass + '-list-wrap']">
<li
:class="[baseClass + '-list']"
v-for="(item, index) in recommendList"
:key="index"
@click="onSearch(item)"
>{{item}}</li>
</ul>
</div>
</div>
</template>
<script>
const mockData = ['123456', '12', '56873', '092341', '454666677']
export default {
data () {
return {
baseClass: 'demo-search',
searchVal: '',
isShowRecommend: false,
recommendList: []
}
},
methods: {
onFoucs () {
this.isShowRecommend = true
},
onBlur () {
this.isShowRecommend = false
this.searchVal = ''
this.recommendList = []
},
onSearch (val) {
val = typeof val === 'string' ? val : this.searchVal
if (val) {
// 這里需要跳轉(zhuǎn)搜索,我們用console來代替
console.log(val)
this.searchVal = ''
} else {
this.$refs['demo-search-input'].focus()
}
},
getRecommendedList () {
if (this.searchVal) {
// 這里需要給后臺(tái)發(fā)送請(qǐng)求來獲取聯(lián)想詞,這里我們用mock數(shù)據(jù)匹配來展示
setTimeout(() => {
const reg = new RegExp(this.searchVal)
const arr = []
for (let i = 0; i < mockData.length; i++) {
if (reg.test(mockData[i])) {
arr.push(mockData[i])
}
}
this.recommendList = arr
}, 10)
}
}
}
}
</script>
上面就是我們這個(gè)效果的代碼了,根據(jù)邏輯來看我們?cè)趇nput上面綁定了blur事件來控制清空搜索和收起聯(lián)想詞下拉列表,同時(shí)給list綁定了click事件,我們的預(yù)期是點(diǎn)擊list的時(shí)候console執(zhí)行然后input失去焦點(diǎn)收起來,但是事實(shí)是它僅僅執(zhí)行了blur,onSearch事件里面的console并未執(zhí)行。
猜測(cè)原因做嘗試
首先第一反應(yīng)絕對(duì)是事件的觸發(fā)順序,所以我就想到了利器setTimeout來驗(yàn)證
onBlur () {
setTimeout(() => {
this.isShowRecommend = false
this.searchVal = ''
this.recommendList = []
}, 500)
}
結(jié)果果然觸發(fā)了,因?yàn)檠舆t了blur先執(zhí)行了click。但是當(dāng)我們點(diǎn)擊其他區(qū)域的時(shí)候下拉窗口需要停頓一會(huì)再消失,這個(gè)很詭異,所以繼續(xù)想辦法調(diào)整。
分析:
- 現(xiàn)在確認(rèn)是事件的優(yōu)先級(jí)的問題了,blur要優(yōu)先于click所以我們需要想辦法替換掉click
- 我們知道click事件是由mousedown事件和mouseup事件組成,同時(shí)mousedown和mouseup觸發(fā)必須在同一個(gè)像素點(diǎn)上才會(huì)觸發(fā)click事件。即鼠標(biāo)點(diǎn)擊: mousedown -> mouseup -> click
- 所以我們來寫一個(gè)demo看一下事件的執(zhí)行順序
methods: {
onClick () {
console.log('click')
},
onMousedown () {
console.log('mousedown')
},
onMouseup () {
console.log('mouseup')
},
onBlur () {
console.log('blur')
}
}
結(jié)果

最后把click替換成mousedown,完成了問題修復(fù)
<li
:class="[baseClass + '-list']"
v-for="(item, index) in recommendList"
:key="index"
@mousedown="onSearch(item)"
>{{item}}</li>
最終效果展示

好了今天的踩坑和填坑運(yùn)動(dòng)結(jié)束,以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- JavaScript實(shí)現(xiàn)HTML導(dǎo)航欄下拉菜單
- JavaScript實(shí)現(xiàn)網(wǎng)頁(yè)下拉菜單效果
- Vue.js下拉菜單組件使用方法詳解
- 淺談Vue.js中如何實(shí)現(xiàn)自定義下拉菜單指令
- js實(shí)現(xiàn)按鈕開關(guān)單機(jī)下拉菜單效果
- js動(dòng)態(tài)設(shè)置select下拉菜單的默認(rèn)選中項(xiàng)實(shí)例
- 純JS實(shí)現(xiàn)出生日期[年月日]下拉菜單效果
- JS實(shí)現(xiàn)點(diǎn)擊下拉菜單把選擇的內(nèi)容同步到input輸入框內(nèi)的實(shí)例
- js阻止默認(rèn)右鍵的下拉菜單方法
- js面向?qū)ο蠓庋b級(jí)聯(lián)下拉菜單列表的實(shí)現(xiàn)步驟
相關(guān)文章
JavaScript學(xué)習(xí)筆記之?dāng)?shù)組去重
這篇文章主要介紹了JavaScript學(xué)習(xí)筆記之?dāng)?shù)組去重的相關(guān)資料,需要的朋友可以參考下2016-03-03
JS將指定的某個(gè)字符全部轉(zhuǎn)換為其他字符實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于JS如何將指定的某個(gè)字符全部轉(zhuǎn)換為其他字符的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
javascript頁(yè)面渲染速度測(cè)試腳本分享
這篇文章主要介紹了javascript頁(yè)面渲染速度測(cè)試腳本,計(jì)算瀏覽器渲染HTML頁(yè)面所需要的時(shí)間,需要的朋友可以參考下2014-04-04
js獲取或設(shè)置當(dāng)前窗口url參數(shù)的小例子
這篇文章介紹了js獲取或設(shè)置當(dāng)前窗口url參數(shù)的小例子,有需要的朋友可以參考一下2013-10-10
分享兩個(gè)手機(jī)訪問pc網(wǎng)站自動(dòng)跳轉(zhuǎn)手機(jī)端網(wǎng)站代碼
這篇文章主要介紹了分享兩個(gè)手機(jī)訪問pc網(wǎng)站自動(dòng)跳轉(zhuǎn)手機(jī)端網(wǎng)站代碼,需要的朋友可以參考下2015-01-01

