js 下拉菜单点击旁边收起实现(踩坑记)


Posted in Javascript onSeptember 29, 2019

背景:

最近在搞一个需求:搜索框,输入时显示联想词下拉列表,当点击联想词跳转到搜索页,如果点击其他部分收起联想的下拉列表。接到需求后第一反应用失焦(blur)去做收起操作避免body的监控,随后就踩坑里了,下面情景再现,一步一步来看这个问题的解决(里面的demo等会用vue实现)

带有bug的版本演示图

js 下拉菜单点击旁边收起实现(踩坑记)

备注:最后的搜索跳转我直接用console代替掉了,但是并没有执行

问题抛出

当我点击上面的联想词的时候它的onSearch并不能执行

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) {
    // 这里需要跳转搜索,我们用console来代替
    console.log(val)
    this.searchVal = ''
   } else {
    this.$refs['demo-search-input'].focus()
   }
  },
  getRecommendedList () {
   if (this.searchVal) {
    // 这里需要给后台发送请求来获取联想词,这里我们用mock数据匹配来展示
    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>

上面就是我们这个效果的代码了,根据逻辑来看我们在input上面绑定了blur事件来控制清空搜索和收起联想词下拉列表,同时给list绑定了click事件,我们的预期是点击list的时候console执行然后input失去焦点收起来,但是事实是它仅仅执行了blur,onSearch事件里面的console并未执行。

猜测原因做尝试

首先第一反应绝对是事件的触发顺序,所以我就想到了利器setTimeout来验证

onBlur () {
 setTimeout(() => {
  this.isShowRecommend = false
  this.searchVal = ''
  this.recommendList = []
 }, 500)
}

结果果然触发了,因为延迟了blur先执行了click。但是当我们点击其他区域的时候下拉窗口需要停顿一会再消失,这个很诡异,所以继续想办法调整。

分析:

  1. 现在确认是事件的优先级的问题了,blur要优先于click所以我们需要想办法替换掉click
  2. 我们知道click事件是由mousedown事件和mouseup事件组成,同时mousedown和mouseup触发必须在同一个像素点上才会触发click事件。即鼠标点击: mousedown -> mouseup -> click
  3. 所以我们来写一个demo看一下事件的执行顺序
methods: {
  onClick () {
   console.log('click')
  },
  onMousedown () {
   console.log('mousedown')
  },
  onMouseup () {
   console.log('mouseup')
  },
  onBlur () {
   console.log('blur')
  }
}

结果

 js 下拉菜单点击旁边收起实现(踩坑记)

最后把click替换成mousedown,完成了问题修复

<li
 :class="[baseClass + '-list']"
 v-for="(item, index) in recommendList"
 :key="index"
 @mousedown="onSearch(item)"
>{{item}}</li>

最终效果展示

js 下拉菜单点击旁边收起实现(踩坑记)

好了今天的踩坑和填坑运动结束,以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js 覆盖和重载 函数
Sep 25 Javascript
通用javascript脚本函数库 方便开发
Oct 13 Javascript
基于jQuery的图片大小自动适应实现代码
Nov 17 Javascript
基于jquery的复制网页内容到WORD的实现代码
Feb 16 Javascript
JavaScript+CSS控制打印格式示例介绍
Jan 07 Javascript
jquery对元素拖动排序示例
Jan 16 Javascript
JavaScript中return false的用法
Mar 12 Javascript
jQuery实现输入框下拉列表树插件特效代码分享
Aug 27 Javascript
封装属于自己的JS组件
Jan 27 Javascript
jquery html动态添加的元素绑定事件详解
May 24 Javascript
js中Number数字数值运算后值不对的解决方法
Feb 28 Javascript
实例分析vue循环列表动态数据的处理方法
Sep 28 Javascript
微信小程序 行的删除和增加操作实现详解
Sep 29 #Javascript
微信小程序 轮播图实现原理及优化详解
Sep 29 #Javascript
为nuxt项目写一个面包屑cli工具实现自动生成页面与面包屑配置
Sep 29 #Javascript
React-redux实现小案例(todolist)的过程
Sep 29 #Javascript
关于layui 实现点击按钮添加一行(方法渲染创建的table)
Sep 29 #Javascript
在Layui中实现开关按钮的效果实例
Sep 29 #Javascript
layui之数据表格--与后台交互获取数据的方法
Sep 29 #Javascript
You might like
网站当前的在线人数
2006/10/09 PHP
了解Joomla 这款来自国外的php网站管理系统
2010/03/11 PHP
js完美解决IE6不支持position:fixed的bug
2015/04/24 Javascript
JS和css实现检测移动设备方向的变化并判断横竖屏幕
2015/05/25 Javascript
Javascript中的方法和匿名方法实例详解
2015/06/13 Javascript
javascript与Python快速排序实例对比
2015/08/10 Javascript
JS把内容动态插入到DIV的实现方法
2016/07/19 Javascript
BootStrap 模态框实现刷新网页并关闭功能
2017/01/04 Javascript
深入解析js轮播插件核心代码的实现过程
2017/04/14 Javascript
详解如何在vue-cli中使用vuex
2018/08/07 Javascript
解决webpack dev-server不能匹配post请求的问题
2018/08/24 Javascript
layui 上传文件_批量导入数据UI的方法
2019/09/23 Javascript
koa2 数据api中间件设计模型的实现方法
2020/07/13 Javascript
记录一次websocket封装的过程
2020/11/23 Javascript
[47:45]Liquid vs OG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python yield 小结和实例
2014/04/25 Python
Python2.7.10以上pip更新及其他包的安装教程
2018/06/12 Python
Python 利用scrapy爬虫通过短短50行代码下载整站短视频
2018/10/29 Python
详解python 爬取12306验证码
2019/05/10 Python
使用Python Pandas处理亿级数据的方法
2019/06/24 Python
初探CSS3中的calc()功能
2015/07/14 HTML / CSS
web页面录屏实现
2019/02/12 HTML / CSS
来自全球大都市的高级街头服饰:Pegador
2018/01/03 全球购物
中国跨境在线时尚零售商:Bellelily
2018/04/06 全球购物
美国折扣香水网站:The Perfume Spot
2020/12/12 全球购物
师范生实习自我鉴定
2013/11/01 职场文书
运动会入场解说词300字
2014/01/25 职场文书
竞选副班长演讲稿
2014/04/24 职场文书
新品发布会策划方案
2014/06/08 职场文书
学习雷锋标语
2014/06/25 职场文书
缓刑人员思想汇报500字
2014/09/12 职场文书
租房协议书范例
2014/10/14 职场文书
企业介绍信范文
2015/01/30 职场文书
汶川大地震感悟
2015/08/10 职场文书
什么是执行力?9个故事告诉您:成功绝非偶然!
2019/07/05 职场文书
python turtle绘图
2022/05/04 Python