快速解决js开发下拉框中blur与click冲突


Posted in Javascript onOctober 10, 2016

在开发中我们会经常遇到blur和click冲突的情况。下面叙述了开发中常遇到的“下拉框”的问题,并提供了两种解决方案。

一、blur和click事件简述

blur事件:当元素失去焦点时触发blur事件;其为表单事件,blur和focus事件不会冒泡,其他表单事件都可以。
click事件:当点击元素时触发click事件;所有元素都有此事件,会产生冒泡。

示例1:blur事件为表单事件

<input type="text" id="tel">
<script>
  document.addEventListener("blur", function(){
    console.log("my document blur");
  });

  var ipt = document.getElementById("tel");
  ipt.addEventListener("blur", function(){
    console.log("my input blur");
  });
</script>
// 输出结果:document为非表单元素
my input blur

示例2:click事件可冒泡

<input type="text" id="tel">
<script>
  document.addEventListener("click", function(){
    console.log("my document click");
  });

  var ipt = document.getElementById("tel");
  ipt.addEventListener("click", function(){
    console.log("my input click");
  });
</script>
// 输出结果:
my input click
my document click

示例3:点击某元素导致前一个元素失去焦点,blur事件优先于click事件

<input type="text" id="ipt">
<input type="button" id="btn" value="点我">
<script>
  var ipt = document.getElementById("ipt");
  ipt.addEventListener("blur", function(){
    console.log("my input blur");
  });

  var btn = document.getElementById("btn");
  btn.addEventListener("click", function(){
    console.log("my button click");
  });
</script>
// 输出结果:
my input blur
my button click

二、下拉框blur和click事件冲突,导致不能正常选择值

实际开发中,我们会经常遇到某一下拉列表框,点击其他元素消失列表框;点击下拉框子元素使其生效的需求。这就会面临冲突问题。

<!-- DOM结构示意 -->
<input type="text" placeholder="请选择姓氏" readonly>
<div class="search-list" data-status="hide">
  <ul>
    <li><a href="javascript:">赵</a></li>
    <li><a href="javascript:">钱</a></li>
    <li><a href="javascript:">孙</a></li>
    <li><a href="javascript:">李</a></li>
  </ul>
</div>
/** 说明:
 * 目前通过ul外层div自定义属性“data-status”控制其是否显示  
 */
(function($){
  $("input").focus(function(){
    // input框获取焦点,展示下拉框
    $(".search-list").attr("data-status", "show");
  }).blur(function(){
    // input框失去焦点,隐藏下拉框
    $(".search-list").attr("data-status", "hide");
  });
  // 选择对应选项,并赋值给input框
  $(".search-list li a").click(function(){
    console.log("执行");
    $("input").val($(this).text());
  });
})(jQuery);

执行上述代码,会出现一个问题,并不能正确获取下拉框中某值。
原因:由于JavaScript为单线程,同一时间只能执行处理一个事件。由上述示例3,可得知“blur优先于click执行”。而在本示例中,由于blur处理程序,会将对应的下拉框展示区隐藏,所以导致其后续click事件并不会执行。上述console的信息也不会被输出。

解决方案1:对blur事件进行延迟,让click先执行。

(function($){
  $("input").focus(function(){
    // input框获取焦点,展示下拉框
    $(".search-list").attr("data-status", "show");
  }).blur(function(){
    setTimeout(function(){
      // input框失去焦点,隐藏下拉框
      $(".search-list").attr("data-status", "hide");
    }, 300);
  });
  // 选择对应选项,并赋值给input框
  $(".search-list li a").click(function(){
    console.log("执行");
    $("input").val($(this).text());
  });
})(jQuery);

三、使用mousedown让其优先执行

示例4:将示例3中的click事件改为mousedown

<input type="text" id="ipt">
<input type="button" id="btn" value="点我">
<script>
  var ipt = document.getElementById("ipt");
  ipt.addEventListener("blur", function(){
    console.log("my input blur");
  });

  var btn = document.getElementById("btn");
  btn.addEventListener("mousedown", function(){
    console.log("my button mousedown");
  });
</script>
// 输出结果:
my button mousedown
my input blur

mousedown事件:当鼠标指针移动到元素上方,并按下鼠标按键时,会发生mousedown事件。
mouseup事件:当在元素上放松鼠标按钮时,会发生mouseup事件。

注意:
(1)mousedown与click 事件不同,mousedown事件仅需要按键被按下,而不需要松开即可发生。
(2)mouseup与click事件不同,mouseup事件仅需要放松按钮。当鼠标指针位于元素上方时,放松鼠标按钮就会触发该事件。

补充:mousedown、mouseup、click

<input type="button" id="btn" value="点我">
var btn = document.getElementById("btn");
btn.addEventListener("mousedown", function(){
  console.log("my button mousedown");
});
btn.addEventListener("click", function(){
  console.log("my button click");
});
btn.addEventListener("mouseup", function(){
  console.log("my button mouseup");
});

输出结果:
my button mousedown
my button mouseup
my button click

所以,其执行顺序为:

mousedown >> mouseup >> click

解决方案2:将click事件改为mousedown,让其优先于blur事件执行

(function($){
  $("input").focus(function(){
    // input框获取焦点,展示下拉框
    $(".search-list").attr("data-status", "show");
  }).blur(function(){
    // input框失去焦点,隐藏下拉框
    $(".search-list").attr("data-status", "hide");
  });
  // 选择对应选项,并赋值给input框
  $(".search-list li a").mousedown(function(){
    $("input").val($(this).text());
  });
})(jQuery);

补充: js、jquery 中 blur事件和click事件冲突

问题说明:
在表单验证中,我们往往会在输入框失去焦点时触发一个blur事件,但当失去焦点后点击了一个按钮,这时blur事件和click事件就都触发了,由于js是单线程的所以就出现了问题,现在需要让blur先执行验证,然后在触发click事件。

解决方法:

给按钮的click事件设置延迟执行setTimeOut(fn,100),延迟时间的设置要大于blur事件的执行时间,这样就会在blur事件执行完后在执行click事件。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery中交替点击事件的实现代码
Feb 14 Javascript
上传文件返回的json数据会被提示下载问题解决方案
Dec 03 Javascript
jQuery操作DOM之获取表单控件的值
Jan 23 Javascript
js+css实现的圆角边框TAB选项卡滑动门代码分享(2款)
Aug 26 Javascript
JS数组合并push与concat区别分析
Dec 17 Javascript
利用vueJs实现图片轮播实例代码
Jun 03 Javascript
JScript实现地址选择功能
Aug 15 Javascript
Node.js创建HTTP文件服务器的使用示例
May 11 Javascript
基于Layui自定义模块的使用方法详解
Sep 14 Javascript
在Vue里如何把网页的数据导出到Excel的方法
Sep 30 Javascript
微信小程序 接入腾讯地图的两种写法
Jan 12 Javascript
关于element的表单组件整理笔记
Feb 05 Javascript
JavaScript 闭包机制详解及实例代码
Oct 10 #Javascript
Javascript 事件冒泡机制详细介绍
Oct 10 #Javascript
JS 滚动事件window.onscroll与position:fixed写兼容IE6的回到顶部组件
Oct 10 #Javascript
javaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序整理总结
Oct 10 #Javascript
jQuery EasyUI tree 使用拖拽时遇到的错误小结
Oct 10 #Javascript
jQuery继承extend用法详解
Oct 10 #Javascript
mvc 、bootstrap 结合分布式图简单实现分页
Oct 10 #Javascript
You might like
最小化数据传输――在客户端存储数据
2006/10/09 PHP
php中3种方法删除字符串中间的空格
2014/03/10 PHP
php 防止表单重复提交两种实现方法
2016/11/03 PHP
PHP中让json_encode不自动转义斜杠“/”的方法
2017/02/28 PHP
PHP针对中英文混合字符串长度判断及截取方法示例
2017/03/31 PHP
在thinkphp5.0路径中实现去除index.php的方式
2019/10/16 PHP
gearman中worker常驻后台,导致MySQL server has gone away的解决方法
2020/02/27 PHP
javascript jQuery $.post $.ajax用法
2008/07/09 Javascript
js判断客户端是iOS还是Android等移动终端的方法
2013/12/11 Javascript
javascript中普通函数的使用介绍
2013/12/19 Javascript
AngularJS中的过滤器filter用法完全解析
2016/04/22 Javascript
JS控制文本域只读或可写属性的方法
2016/06/24 Javascript
Servlet实现文件上传,可多文件上传示例
2016/12/05 Javascript
jquery PrintArea 实现票据的套打功能(代码)
2017/03/17 Javascript
node通过express搭建自己的服务器
2017/09/30 Javascript
详解ECMAScript typeof用法
2018/07/25 Javascript
VUE中v-on:click事件中获取当前dom元素的代码
2018/08/22 Javascript
如何封装了一个vue移动端下拉加载下一页数据的组件
2019/01/06 Javascript
原生JS forEach()和map()遍历的区别、兼容写法及jQuery $.each、$.map遍历操作
2019/02/27 jQuery
JavaScript中将值转换为字符串的五种方法总结
2019/06/06 Javascript
layui下拉框获取下拉值(select)的例子
2019/09/10 Javascript
浅谈Webpack4 Tree Shaking 终极优化指南
2019/11/18 Javascript
vue使用微信扫一扫功能的实现代码
2020/04/11 Javascript
微信小程序实现电子签名并导出图片
2020/05/27 Javascript
[01:07:13]TNC vs Pain 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
对python中的six.moves模块的下载函数urlretrieve详解
2018/12/19 Python
Python实现二叉搜索树BST的方法示例
2019/07/30 Python
win10系统下python3安装及pip换源和使用教程
2020/01/06 Python
python dumps和loads区别详解
2020/02/04 Python
浅谈HTML5 defer和async的区别
2016/06/07 HTML / CSS
娇韵诗加拿大官网:Clarins加拿大
2017/11/20 全球购物
爱尔兰最大的体育零售商:Life Style Sports
2019/06/12 全球购物
工艺员岗位职责
2014/02/11 职场文书
股东合作协议书范本
2014/04/14 职场文书
小学语文业务学习材料
2014/06/02 职场文书
酒店温馨提示语
2015/07/14 职场文书