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 相关文章推荐
xml分页+ajax请求数据源+dom取结果实例代码
Oct 31 Javascript
IE的有条件注释判定IE版本详解(附实例代码)
Jan 04 Javascript
关于JavaScript的面向对象和继承有利新手学习
Jan 11 Javascript
基于jquery实现后台左侧菜单点击上下滑动显示
Apr 11 Javascript
探讨JavaScript中的Rest参数和参数默认值
Jul 29 Javascript
JavaScript遍历求解数独问题的主要思路小结
Jun 12 Javascript
js 创建对象 经典模式全面了解
Aug 16 Javascript
vuejs父子组件通信的问题
Jan 11 Javascript
jquery中each循环的简单回滚操作
May 05 jQuery
在vue项目中引入vue-beauty操作方法
Feb 11 Javascript
JavaScript实现无限级递归树的示例代码
Mar 29 Javascript
ElementUI radio组件选中小改造
Aug 12 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
php中关于codeigniter的xmlrpc的类在进行数据交换时的类型问题
2011/07/03 PHP
基于flush()不能按顺序输出时的解决办法
2013/06/29 PHP
PHP中将ip地址转成十进制数的两种实用方法
2013/08/15 PHP
解析WordPress中函数钩子hook的作用及基本用法
2015/12/22 PHP
PHP读取目录树的实现方法分析
2019/03/22 PHP
JQuery 解析多维的Json数据格式
2009/11/02 Javascript
jQuery EasyUI API 中文文档 - Panel面板
2011/09/30 Javascript
如何使Chrome控制台支持多行js模式——意外发现
2013/06/13 Javascript
javascript与cookie 的问题详解
2013/11/11 Javascript
利用JS屏蔽页面中的Enter按键提交表单的方法
2016/11/25 Javascript
Javascript中构造函数要注意的一些坑
2017/01/23 Javascript
node.js爬虫爬取拉勾网职位信息
2017/03/14 Javascript
详解用webpack2搭建angular2的项目
2017/06/22 Javascript
微信小程序如何获取用户信息
2018/01/26 Javascript
vue模式history下在iis中配置流程
2019/04/17 Javascript
DWR内存兼容及无法调用问题解决方案
2020/10/16 Javascript
[00:58]PWL开团时刻DAY5——十人开雾0换5
2020/11/04 DOTA
python中Genarator函数用法分析
2015/04/08 Python
浅谈python jieba分词模块的基本用法
2017/11/09 Python
Python爬虫包BeautifulSoup实例(三)
2018/06/17 Python
Python函数装饰器实现方法详解
2018/12/22 Python
python实现串口自动触发工作的示例
2019/07/02 Python
Python字符串的修改方法实例
2019/12/19 Python
浅析Python数字类型和字符串类型的内置方法
2019/12/22 Python
python实现四人制扑克牌游戏
2020/04/22 Python
python实现测试工具(二)——简单的ui测试工具
2020/10/19 Python
python中scipy.stats产生随机数实例讲解
2021/02/19 Python
瑜伽灵感珠宝:Satya Jewelry
2018/01/06 全球购物
土木工程专业个人求职信
2013/12/30 职场文书
2014年元旦感言
2014/03/06 职场文书
支部组织生活会方案
2014/06/10 职场文书
教师遵守党的政治纪律情况对照检查材料
2014/09/26 职场文书
解除劳动关系协议书2篇
2014/11/28 职场文书
初婚未育证明样本
2015/06/18 职场文书
教你使用TensorFlow2识别验证码
2021/06/11 Python
win10蓝屏0xc0000001安全模式进不了怎么办?win10出现0xc0000001的解决方法
2022/08/05 数码科技