js 下拉菜单点击旁边收起实现(踩坑记)

 更新时间:2019年09月29日 11:32:23   作者:jingqian_xi  
这篇文章主要介绍了js 下拉菜单点击旁边收起实现(踩坑记),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

背景:

最近在搞一个需求:搜索框,输入时显示联想词下拉列表,当点击联想词跳转到搜索页,如果点击其他部分收起联想的下拉列表。接到需求后第一反应用失焦(blur)去做收起操作避免body的监控,随后就踩坑里了,下面情景再现,一步一步来看这个问题的解决(里面的demo等会用vue实现)

带有bug的版本演示图

备注:最后的搜索跳转我直接用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')
  }
}

结果

 

最后把click替换成mousedown,完成了问题修复

<li
 :class="[baseClass + '-list']"
 v-for="(item, index) in recommendList"
 :key="index"
 @mousedown="onSearch(item)"
>{{item}}</li>

最终效果展示

好了今天的踩坑和填坑运动结束,以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 通俗解释JavaScript正则表达式快速记忆

    通俗解释JavaScript正则表达式快速记忆

    正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。简单来说,就是按照某种规则去匹配符合条件的字符串
    2017-08-08
  • JavaScript学习笔记之数组去重

    JavaScript学习笔记之数组去重

    这篇文章主要介绍了JavaScript学习笔记之数组去重的相关资料,需要的朋友可以参考下
    2016-03-03
  • JS将指定的某个字符全部转换为其他字符实例代码

    JS将指定的某个字符全部转换为其他字符实例代码

    这篇文章主要给大家介绍了关于JS如何将指定的某个字符全部转换为其他字符的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • javascript页面渲染速度测试脚本分享

    javascript页面渲染速度测试脚本分享

    这篇文章主要介绍了javascript页面渲染速度测试脚本,计算浏览器渲染HTML页面所需要的时间,需要的朋友可以参考下
    2014-04-04
  • 微信小程序实战之打卡时钟的绘制

    微信小程序实战之打卡时钟的绘制

    这篇文章主要介绍了如何利用微信小程序制作一个打卡时钟,分为工作和休息两种状态,用户可以设置相应的时间,所有的时钟记录都会被保存下来,感兴趣的可以了解一下
    2022-04-04
  • js获取或设置当前窗口url参数的小例子

    js获取或设置当前窗口url参数的小例子

    这篇文章介绍了js获取或设置当前窗口url参数的小例子,有需要的朋友可以参考一下
    2013-10-10
  • 浅析ES6与CommonJS中模块的用法对比

    浅析ES6与CommonJS中模块的用法对比

    ES6 的模块化汲取了 CommonJS 和AMD 的优点,拥有简洁的语法和异步的支持,并且写法也和 CommonJS 非常的相似,下面我们就来看看二者用法的差异吧
    2023-09-09
  • JS常用字符串方法(推荐)

    JS常用字符串方法(推荐)

    下面小编就为大家带来一篇JS常用字符串方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • 分享两个手机访问pc网站自动跳转手机端网站代码

    分享两个手机访问pc网站自动跳转手机端网站代码

    这篇文章主要介绍了分享两个手机访问pc网站自动跳转手机端网站代码,需要的朋友可以参考下
    2015-01-01
  • 再谈JavaScript线程

    再谈JavaScript线程

    继上篇讨论了一些关于JavaScript线程的知识,我们不妨回过头再看看,是不是JavaScript就不能多线程呢?看下面一段很简单的代码(演示用,没考虑兼容问题):
    2015-07-07

最新评论