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 24 Javascript
javascript一个无懈可击的实例化XMLHttpRequest的方法
Oct 13 Javascript
JavaScript的setAttribute兼容性问题解决方法
Nov 11 Javascript
javascript读取Xml文件做一个二级联动菜单示例
Mar 17 Javascript
javascript框架设计之种子模块
Jun 23 Javascript
基于jquery实现左右按钮点击的图片切换效果
Jan 27 Javascript
jquery实现二级导航下拉菜单效果
Dec 18 Javascript
vue实现ToDoList简单实例
Feb 07 Javascript
js实现首屏延迟加载实现方法 js实现多屏单张图片延迟加载效果
Jul 17 Javascript
vue 微信授权登录解决方案
Apr 10 Javascript
vue实现配置全局访问路径头(axios)
Nov 01 Javascript
react中的DOM操作实现
Jun 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
php Static关键字实用方法
2010/06/04 PHP
php中jQuery插件autocomplate的简单使用笔记
2012/06/14 PHP
Smarty模板学习笔记之Smarty简介
2014/05/20 PHP
js代码实现微博导航栏
2015/07/30 PHP
基于Laravel(5.4版本)的基本增删改查操作方法
2019/10/11 PHP
JavaScript 动态生成方法的例子
2009/07/22 Javascript
JQUERY 浏览器判断实现函数
2009/08/20 Javascript
javascript中的一些注意事项 更新中
2010/12/06 Javascript
JS的千分位算法实现思路
2013/07/31 Javascript
JavaScript静态类型检查工具FLOW简介
2015/01/06 Javascript
深入理解JavaScript编程中的原型概念
2015/06/25 Javascript
AngularJS基础 ng-if 指令用法
2016/08/01 Javascript
基于jQuery实现表格的排序
2016/12/02 Javascript
jquery制作的移动端购物车效果完整示例
2020/02/24 jQuery
使用vue打包进行云服务器上传的问题
2020/03/02 Javascript
[00:57]辉夜杯战队访谈宣传片—VG
2015/12/25 DOTA
[13:56]DAC2018 4.5SOLO赛决赛 MidOne vs Paparazi第一场
2018/04/06 DOTA
python 中文字符串的处理实现代码
2009/10/25 Python
Python多线程爬虫实战_爬取糗事百科段子的实例
2017/12/15 Python
Python 装饰器实现DRY(不重复代码)原则
2018/03/05 Python
使用 Python 玩转 GitHub 的贡献板(推荐)
2019/04/04 Python
python字符串和常用数据结构知识总结
2019/05/21 Python
python3+PyQt5 自定义窗口部件--使用窗口部件样式表的方法
2019/06/26 Python
python爬虫请求头设置代码
2020/07/28 Python
HTML5之SVG 2D入门10—滤镜的定义及使用
2013/01/30 HTML / CSS
Ooni英国官网:披萨烤箱
2020/05/31 全球购物
既然说Ruby中一切都是对象,那么Ruby中类也是对象吗
2013/01/26 面试题
教学个人的自我评价分享
2014/02/16 职场文书
创建无烟单位实施方案
2014/03/29 职场文书
装修协议书范本
2014/04/21 职场文书
大学生撤销处分思想汇报
2014/09/12 职场文书
2014物价局群众路线对照检查材料思想汇报
2014/09/21 职场文书
2014年信访维稳工作总结
2014/12/08 职场文书
幼师求职自荐信
2015/03/26 职场文书
横空出世观后感
2015/06/09 职场文书
台积电称即便经济低迷也没有降价的计划
2022/04/21 数码科技