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实现省市联动效果的简单实例
Feb 10 Javascript
jQuery+HTML5加入购物车代码分享
Oct 29 Javascript
jquery 实现输入邮箱时自动补全下拉提示功能
Oct 04 Javascript
Bootstrap每天必学之下拉菜单
Nov 25 Javascript
利用jsonp跨域调用百度js实现搜索框智能提示
Aug 24 Javascript
AngularJS使用自定义指令替代ng-repeat的方法
Sep 17 Javascript
微信开发 使用picker封装省市区三级联动模板
Oct 28 Javascript
JavaScript中undefined和null的区别
May 03 Javascript
vue+mockjs模拟数据实现前后端分离开发的实例代码
Aug 08 Javascript
微信小程序分享功能之按钮button 边框隐藏和点击隐藏
Jun 14 Javascript
微信小程序判断用户是否需要再次授权获取个人信息
Jul 18 Javascript
vue实现把接口单独存放在一个文件方式
Aug 13 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
如何解决CI框架的Disallowed Key Characters错误提示
2013/07/05 PHP
8个必备的PHP功能开发
2015/10/02 PHP
php生成高清缩略图实例详解
2015/12/07 PHP
PHP二维数组实现去除重复项的方法【保留各个键值】
2017/12/21 PHP
解决laravel(5.5)访问public报错的问题
2019/10/12 PHP
JavaScript 解析Json字符串的性能比较分析代码
2009/12/16 Javascript
jQuery Animation实现CSS3动画示例介绍
2013/08/14 Javascript
JQuery实现鼠标滑过显示导航下拉列表
2013/09/12 Javascript
JS实现拖动示例代码
2013/11/01 Javascript
jQuery中$.fn的用法示例介绍
2013/11/05 Javascript
浅析offsetLeft,Left,clientLeft之间的区别
2013/11/30 Javascript
jquery实现类似淘宝星星评分功能实例
2014/09/12 Javascript
jquery实现最简单的滑动菜单效果代码
2015/09/12 Javascript
深入理解jQuery事件绑定
2016/06/02 Javascript
ReactNative实现图片上传功能的示例代码
2017/07/11 Javascript
JavaScript中in和hasOwnProperty区别详解
2017/08/04 Javascript
JS使用正则表达式找出最长连续子串长度
2017/10/26 Javascript
在vue中使用SockJS实现webSocket通信的过程
2018/08/29 Javascript
MockJs结合json-server模拟后台数据
2020/08/26 Javascript
vue解决使用$http获取数据时报错的问题
2019/10/30 Javascript
vue 解决uglifyjs-webpack-plugin打包出现报错的问题
2020/08/04 Javascript
安装dbus-python的简要教程
2015/05/05 Python
Pycharm 设置自定义背景颜色的图文教程
2018/05/23 Python
Python Opencv实现图像轮廓识别功能
2020/03/23 Python
正则给header的冒号两边参数添加单引号(Python请求用)
2019/08/09 Python
Django发送邮件功能实例详解
2019/09/02 Python
python 异步async库的使用说明
2020/05/04 Python
Python模拟登录和登录跳转的参考示例
2020/10/30 Python
html5音频_动力节点Java学院整理
2018/08/22 HTML / CSS
世界各地的当地人的食物体验:Eatwith
2019/07/26 全球购物
学生拾金不昧表扬信
2014/01/21 职场文书
公司保密承诺书
2014/03/27 职场文书
高一学年自我鉴定范文(3篇)
2014/09/26 职场文书
小学生校园广播稿
2014/09/28 职场文书
长江三峡导游词
2015/01/31 职场文书
优秀乡村医生事迹材料(2016精选版)
2016/02/29 职场文书