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 相关文章推荐
IE bug table元素的innerHTML
Jan 11 Javascript
JS获取Table中td值的方法
Mar 19 Javascript
js正则表达式匹配数字字母下划线等
Apr 14 Javascript
js时钟翻牌效果实现代码分享
Jul 31 Javascript
分享一个插件实现水珠自动下落效果
Jun 01 Javascript
JavaScript随机生成颜色的方法
Oct 15 Javascript
jQuery中的一些小技巧
Jan 18 Javascript
javascript 判断当前浏览器版本并判断ie版本
Feb 17 Javascript
jQuery使用ajax_动力节点Java学院整理
Jul 05 jQuery
Vue.js 实现微信公众号菜单编辑器功能(一)
May 08 Javascript
Vue-Router的使用方法
Sep 05 Javascript
springboot+vue实现文件上传下载
Nov 17 Vue.js
微信小程序 行的删除和增加操作实现详解
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数组及条件,循环语句学习
2012/11/11 PHP
Php output buffering缓存及程序缓存深入解析
2013/07/15 PHP
PHP vsprintf()函数格式化字符串操作原理解析
2020/07/14 PHP
Add a Formatted Table to a Word Document
2007/06/15 Javascript
当jQuery遭遇CoffeeScript的时候 使用分享
2011/09/17 Javascript
获取内联和链接中的样式(js代码)
2013/04/11 Javascript
js格式化货币数据实现代码
2013/09/04 Javascript
jquery append()方法与html()方法的区别及使用介绍
2014/08/01 Javascript
JQuery EasyUI Layout 在from布局自适应窗口大小的实现方法
2016/05/28 Javascript
EasyUI Combobox设置默认值 获取text的方法
2016/11/28 Javascript
浅析js的模块化编写 require.js
2016/12/07 Javascript
Node.js EventEmmitter事件监听器用法实例分析
2019/01/07 Javascript
解决在Vue中使用axios用form表单出现的问题
2019/10/30 Javascript
vuex存储token示例
2019/11/11 Javascript
使用pkg打包ThinkJS项目的方法步骤
2019/12/30 Javascript
Python实现批量下载文件
2015/05/17 Python
Python生成器定义与简单用法实例分析
2018/04/30 Python
python找出完数的方法
2018/11/12 Python
python selenium操作cookie的实现
2020/03/18 Python
使用tensorflow框架在Colab上跑通猫狗识别代码
2020/04/26 Python
Python实现邮件发送的详细设置方法(遇到问题)
2021/01/18 Python
打架检讨书50字
2014/01/11 职场文书
学校七一活动方案
2014/01/19 职场文书
幼儿园教学随笔感言
2014/02/23 职场文书
外语系毕业生求职自荐信
2014/04/12 职场文书
搞笑爱情保证书
2014/04/29 职场文书
大学生工作求职信
2014/06/23 职场文书
会计实训报告范文
2014/11/04 职场文书
毕业生个人总结
2015/02/28 职场文书
个人政治思想总结
2015/03/05 职场文书
2015年度团总支工作总结
2015/04/23 职场文书
广告策划的实习心得体会总结!
2019/07/22 职场文书
Python词云的正确实现方法实例
2021/05/08 Python
Django如何创作一个简单的最小程序
2021/05/12 Python
仅仅使用 HTML/CSS 实现各类进度条的方式汇总
2021/11/11 HTML / CSS
mysql函数之截取字符串的实现
2022/08/14 MySQL