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 模拟实现类似c#下的hashtable的简单功能代码
Jan 24 Javascript
JavaScript中的prototype使用说明
Apr 13 Javascript
基于jQuery的message插件实现右下角弹出消息框
Jan 11 Javascript
深入理解Javascript动态方法调用与参数修改的问题
Dec 10 Javascript
jQuery对下拉框,单选框,多选框的操作
Feb 21 Javascript
JS实现仿FLASH效果的竖排导航代码
Sep 15 Javascript
基于JQuery实现的跑马灯效果(文字无缝向上翻动)
Dec 02 Javascript
浅谈js中用$(#ID)来作为选择器的问题(id重复的时候)
Feb 14 Javascript
AngularJS中$http的交互问题
Mar 29 Javascript
分享Bootstrap简单表格、表单、登录页面
Aug 04 Javascript
vue实现element表格里表头信息提示功能(推荐)
Nov 20 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
May 11 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
Excel数据导入Mysql数据库的实现代码
2008/06/05 PHP
屏蔽PHP默认设置中的Notice警告的方法
2016/05/20 PHP
分析PHP中单双引号的误区和双引号小隐患
2016/07/19 PHP
PHP基于SMTP协议实现邮件发送实例代码
2017/04/27 PHP
Mac系统下安装PHP Xdebug
2018/03/30 PHP
网页开发中的容易忽略的问题 javascript HTML中的table
2009/04/15 Javascript
JS 获取span标签中的值的代码 支持ie与firefox
2009/08/24 Javascript
jquery.blockUI.js上传滚动等待效果实现思路及代码
2013/03/18 Javascript
js判断手机端(Android手机还是iPhone手机)
2015/07/22 Javascript
JS实现的最简Table选项卡效果
2015/10/14 Javascript
JavaScript获取ul中li个数的方法
2017/02/13 Javascript
jQuery实现大图轮播
2017/02/13 Javascript
vue.js的提示组件
2017/03/02 Javascript
Vue2.0用户权限控制解决方案的示例
2018/02/10 Javascript
vue移动端弹框组件的实例
2018/09/25 Javascript
vue.js实现的全选与全不选功能示例【基于elementui】
2018/12/03 Javascript
vue项目在webpack2实现移动端字体自适配功能
2020/06/02 Javascript
vue cli 3.0通用打包配置代码,不分一二级目录
2020/09/02 Javascript
[10:42]Team Liquid Vs Newbee
2018/06/07 DOTA
Pycharm设置utf-8自动显示方法
2019/01/17 Python
Python3和pyqt5实现控件数据动态显示方式
2019/12/13 Python
windows10环境下用anaconda和VScode配置的图文教程
2020/03/30 Python
html5清空画布方法(三种)
2017/10/16 HTML / CSS
人力资源经理的岗位职责范本
2014/02/28 职场文书
校庆活动方案
2014/03/31 职场文书
初中班主任评语大全
2014/04/24 职场文书
铁路安全事故反思
2014/04/26 职场文书
大学生个人求职信
2014/06/02 职场文书
副总经理岗位职责
2015/02/02 职场文书
武当山导游词
2015/02/03 职场文书
生日宴会家属答谢词
2015/09/29 职场文书
《我的伯父鲁迅先生》教学反思
2016/02/16 职场文书
导游词之四川武侯祠
2019/10/21 职场文书
浅谈PostgreSQL表分区的三种方式
2021/06/29 PostgreSQL
Ruby使用Mysql2连接操作MySQL
2022/04/19 Ruby