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打包类,基本可以实现所有的滚动效果,太强了
Dec 08 Javascript
JavaScript获取GridView中用户点击控件的行号,列号
Apr 14 Javascript
使用javascript获取flash加载的百分比的实现代码
May 25 Javascript
jquery easyui中treegrid用法的简单实例
Feb 18 Javascript
js定时调用方法成功后并停止调用示例
Apr 08 Javascript
javascript中expression的用法整理
May 13 Javascript
AngularJS表格样式简单设置方法示例
Mar 03 Javascript
vue2.0结合DataTable插件实现表格动态刷新的方法详解
Mar 17 Javascript
深入理解AngularJS中的ng-bind-html指令
Mar 27 Javascript
jQuery表单设置值的方法
Jun 30 jQuery
express框架下使用session的方法
Jul 31 Javascript
解析JS在获取当前月的最后一天遇到的坑
Aug 30 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
YII中assets的使用示例
2014/07/31 PHP
php分割合并两个字符串的函数实例
2015/06/19 PHP
PHP扩展迁移为PHP7扩展兼容性问题记录
2016/02/15 PHP
对xmlHttp对象方法和属性的理解
2011/01/17 Javascript
node.js中使用node-schedule实现定时任务实例
2014/06/03 Javascript
Javascript验证用户输入URL地址是否为空及格式是否正确
2014/10/09 Javascript
JQuery boxy插件在IE中边角图片不显示问题的解决
2015/05/20 Javascript
Cropper.js 实现裁剪图片并上传(PC端)
2017/08/20 Javascript
vue.js,ajax渲染页面的实例
2018/02/11 Javascript
浅谈vue引用静态资源需要注意的事项
2018/09/28 Javascript
JS实现贪吃蛇游戏
2019/11/15 Javascript
Vue-router 报错NavigationDuplicated的解决方法
2020/03/31 Javascript
vue el-tree 默认展开第一个节点的实现代码
2020/05/15 Javascript
解决VueCil代理本地proxytable无效报错404的问题
2020/11/07 Javascript
在VUE中使用lodash的debounce和throttle操作
2020/11/09 Javascript
vue中配置scss全局变量的步骤
2020/12/28 Vue.js
[46:38]完美世界DOTA2联赛PWL S2 Magma vs PXG 第三场 11.28
2020/12/02 DOTA
python操作摄像头截图实现远程监控的例子
2014/03/25 Python
Python脚本实现自动发带图的微博
2016/04/27 Python
Python+matplotlib实现华丽的文本框演示代码
2018/01/22 Python
Python Pandas批量读取csv文件到dataframe的方法
2018/10/08 Python
python实现字符串和数字拼接
2020/03/02 Python
Python 如何批量更新已安装的库
2020/05/26 Python
我们是伦敦女孩:WalG
2018/01/08 全球购物
澳大利亚便宜隐形眼镜购买网站:QUICKLENS Australia
2018/10/06 全球购物
Hawes & Curtis澳大利亚官网:英国经典服饰品牌
2018/10/29 全球购物
Elemental Herbology官网:英国美容品牌
2019/04/27 全球购物
在线实验室测试:HealthLabs.com
2020/05/03 全球购物
毕业生求职信的经典写法
2014/01/31 职场文书
党员自我剖析材料
2014/08/31 职场文书
农村党支部书记四风问题个人对照检查材料
2014/09/21 职场文书
小班教师个人总结
2015/02/05 职场文书
电气工程师岗位职责
2015/02/12 职场文书
2019年关于小学生课外阅读情况的分析报告
2019/12/02 职场文书
Python学习之迭代器详解
2022/04/01 Python
Python TypeError: ‘float‘ object is not subscriptable错误解决
2022/12/24 Python