还原车祸现场

功能类似于百度搜索,搜索框输入内容,下拉框显示候选项,点击候选项就选择候选项,然后下拉框隐藏,点击外面就直接隐藏下拉框,于是我写了以下代码

//参会单位联想
$('input[name="company_name"]').bind('input propertychange', function() {
var _this = this;
clearTimeout(this.timer);
this.timer = setTimeout(function(){
$.ajax({
url:domin+'/api/company/index',
data:{
k:_this.value
},
dataType:'jsonp',
success:function(res){
if(res.status.code==0){
if(res.data.length<=0) return false;
var str = "";
res.data.forEach(function(e,i){
str += '<dd data-value="'+e.id+'" data-type="'+e.role_code+'" class="">'+e.name+'</dd>';
})
$('#company_list').html(str);
$(_this).parent().addClass('layui-form-selected');
}else {
form.val("beforehand", {
"company-type": "",
});
}
}
})
}, 1000);
$('#company_list').on('click','dd',function(){
_this.value = this.innerHTML;
postData.company_id = $(this).data('value');
form.val("beforehand", {
"company-type": company_type[$(this).data('type')]?company_type[$(this).data('type')]:"普通",
});
$(_this).parent().removeClass('layui-form-selected');
$(this).parent().html('');
isSelect = false;
})
});
$('input[name="company_name"]').blur(function(ev){
  $('input[name="company_name"]').parent().removeClass('layui-form-selected');
})

先去请求数据,然后渲染列表,然后监听候选项点击,最后blur的时候隐藏下拉框,觉得自己写的很完美,于是便兴冲冲的去测试,但是一测试我发现了大问题,在我点击列表项也就是 dd 的时候,下拉框直接隐藏了,候选项的内容也没有被填到input里面去。我便很费解,于是便去找度娘玩耍,众说纷纭,我在很多胡扯的评论中终于找到了。总结如下,看看完整的步骤

  1. 点击 dd ,此时先触发 mousedown
  2. input 的 blur 触发
  3. 下拉框消失
  4. 此时鼠标抬起并不是在下拉框上
  5. dd 的 click 并没有触发

解决方案

  1. 监听的document的mouseup而不是input的blur事件,这样先触发dd的mouseup,此时数据就已经取到,然后冒泡到document,移除下拉框(类似于百度搜索)
  2. 监听dd的mousedown,这也会先取值,然后input再失焦(体验不太好,用户按下就会触发,不允许纠结,比如我按下第一个的时候,突然想选择第二个)
  3. dd还是,input还是blur,全局定义一个isSelect变量,监听dl的mousedown 触发以后修改isSelect = true ,这样在blur时,先判断isSelect 就好了。(代码如下)
var isSelect = false;
// some code
$('#company_list').on('click','dd',function(){
    _this.value = this.innerHTML;
    postData.company_id = $(this).data('value');
    form.val("beforehand", {
      "company-type": company_type[$(this).data('type')]?company_type[$(this).data('type')]:"普通",
    });
    $(_this).parent().removeClass('layui-form-selected');
    $(this).parent().html('');
    isSelect = false; //++
  })
// some code
// 以下为新增
$('#company_list').mousedown(function(){
  // 下拉框mousedown时,保存下拉框为真
  isSelect = true;
  // 注册定时器 0毫秒以后触发,在定时器触发之前 ,input 的失焦事件触发此时isSelect为真
  setTimeout(function(){
    // 此时input的失焦已经触发了
    isSelect = false;
    $('input[name="company_name"]').focus()
  },0)
})
$('input[name="company_name"]').blur(function(ev){
  if(!isSelect){//++
    $('input[name="company_name"]').parent().removeClass('layui-form-selected');
  }//++
})

虽然 setTimeout 是0毫秒的延迟,但是他在下一次的事件队列中,所以会先执行 input 的 blur 事件,再执行 setTimeout 。

有关事件循环 EventLoop 的知识,大家可以自行百度,理解了这个,虽然不会让你写代码变厉害,但是对理解js是有很大的作用的。不过想彻底理解,需要理解宏任务 task 与微任务 Microtasks ,以及 Promise 。

下次可能会写一下关于 EventLoop 的东西。

下拉框click事件与搜索框blur事件的爱恨纠葛的更多相关文章

  1. ideal取消按下两次shift弹出搜索框 修改idea,webstrom,phpstrom 快捷键double shift 弹出search everywhere

    因为经常需要在中英文之间切换,所以时常使用shift键,一不小心就把这个Searchwhere 对话框调出来了,很是麻烦. 因此痛定思痛, 我决定将这个按两下shift键就弹出搜索框的快捷键禁用了! ...

  2. 下拉选择select和复选框checkbox的状态的各种方式

    复选框的状态 <input name="ck" value=" " type="checkbox"  checked> 或者&l ...

  3. jQuery 滚动条 滚动到底部(下拉到底部) 加载数据(触发事件、处理逻辑)、分页加载数据

    1.针对浏览器整个窗口滚动 主要代码: <script type="text/javascript"> ; function GetProductListPageFun ...

  4. Html5+Mui前端框架,开发记录(四):下拉菜单绑定数据、搜索、时间控件

    1.下拉菜单绑定数据,选择后回传值 1)html: <div class="mui-input-row"> <label>xxx:</label> ...

  5. input输入框的的input事件和change事件以及change和blur事件的区别

    input输入框的 oninput事件 ,在用户输入的时候触发,只要元素值发生变化就会触发 input输入框的 onchange事件 ,要在输入框失去焦点的时候触发事件,当鼠标在其他地方点击一下才会触 ...

  6. 开发手机APP过程,不同使用场景APP搜索框的样式及区别

    搜索框是 app 内最常见的控件之一,可以帮助用户快速又精准找到期望的内容与功能.不同的使用场景下,根据页面中搜索的重要程度,搜索框也有着不同的样式. 下面就常州开发APP公司和大家聊聊常见的四种样式 ...

  7. typecho博客组插件:openSug.js百度搜索框下拉提示免费代码

      Typecho候选搜索增强插件:安装openSug插件即可获得带有“搜索框提示”功能的搜索框,让Typecho搜索更便捷! 支持百度.谷歌.雅虎.Yandex.360好搜.UC神马.酷狗.优酷.淘 ...

  8. z-blog博客组插件openSug.js百度搜索下拉框提示代码

      z-blog安装openSug插件即可获得带有“搜索框提示”功能的搜索框,让z-blog搜索更便捷! https://www.opensug.org/.../opensug_z-blog_v1.0 ...

  9. Discuz论坛搜索下拉框插件openSug

    Discuz!只需安装openSug插件即可获得带有“搜索框提示”功能的搜索框,让您的Discuz搜索更便捷! 下载:https://www.opensug.org/faq/.../opensug.d ...

随机推荐

  1. openlayers应用原理

    1.数据组织 OpenLayers通过同层(Layer)进行组织渲染,然后通过数据源设置具体的地图数据来源.因此,Layer与Source是密切相关的对应关系,缺一不可.Layer可看做渲染地图的层容 ...

  2. 抓包分析、多线程爬虫及xpath学习

    1.抓包分析 1.1 Fiddler安装及基本操作 由于很多网站采用的是HTTPS协议,而fiddler默认不支持HTTPS,先通过设置使fiddler能抓取HTTPS网站,过程可参考(https:/ ...

  3. 音频 m4a 转 wav

    背景 最近做智能家居,需要用到一些应答词 需要自己录制.但是在mac下面通过 QuickTime 录制的是 m4a格式.但是应答词需要 wav格式.所以就需要转化了 解决方法 # sox 不行, ff ...

  4. 用servlet进行用户名和密码校验1

    运行效果如下: 代码截图: 登陆网页: 显示网页: 网盘链接: 链接:https://pan.baidu.com/s/1g5XJ6y8u5R5Wt0Lkj9g9lg 提取码:bphb

  5. Setup Factory使用

  6. js之history

    浏览历史记录window.history,不会刷新页面内容,只会更改历史记录,用location.href 才会刷新 1. history.pushState() & history.repl ...

  7. spark核心优化详解

    大家好!转眼又到了经验分享的时间了.吼吼,我这里没有摘要也没有引言,只有单纯的经验分享,请见谅哦! 言归正传,目前在大数据领域能够提供的核心计算的工具,如离线计算hadoop生态圈的mr计算模型,以及 ...

  8. static与volatile的用法

      static 1.概述 static 声明的变量在C语言中有两方面的特征: 1).变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值.这一点是它与堆栈变量和堆变量的区别 ...

  9. 【托业】【全真题库】TEST2-语法题

    105 to do sth 不定时可充当形容词修饰名词 In an effort to reduce prices----为降低价格 106. 修饰比较级:far,much,even,still,a ...

  10. vue/cli3 配置相对路径

    根目录下新建 vue.config.js 文件 const path = require('path') function resolve(dir){ return path.join(__dirna ...