快速解决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选择器计算table中的某一列某一行的合计
Aug 13 Javascript
jQuery 和 CSS 的文本特效插件集锦
Dec 12 Javascript
javascript编写贪吃蛇游戏
Jul 07 Javascript
原生js的数组除重复简单实例
May 24 Javascript
Javascript 判断两个IP是否在同一网段实例代码
Nov 28 Javascript
JavaScript轻松创建级联函数的方法示例
Feb 10 Javascript
JavaWeb表单及时验证功能在输入后立即验证(含用户类型,性别,爱好...的验证)
Jun 09 Javascript
详解react内联样式使用webpack将px转rem
Sep 13 Javascript
JS实现li标签的删除
Apr 12 Javascript
微信小程序获取用户信息并保存登录状态详解
May 10 Javascript
vue使用video.js进行视频播放功能
Jul 18 Javascript
layui的布局和表格的渲染以及动态生成表格的方法
Sep 18 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
windows xp下安装pear
2006/12/02 PHP
解析ajax事件的调用顺序
2013/06/17 PHP
Zend Framework教程之Zend_Config_Ini用法分析
2016/03/23 PHP
PHP简单检测网址是否能够正常打开的方法
2016/09/04 PHP
php使用 readfile() 函数设置文件大小大小的方法
2017/08/11 PHP
php strftime函数的详细用法
2018/06/21 PHP
Nigma vs Liquid BO3 第一场2.13
2021/03/10 DOTA
js 表单验证方法(实用)
2009/04/28 Javascript
让iframe子窗体取父窗体地址栏参数(querystring)
2009/10/13 Javascript
js 编写规范
2010/03/03 Javascript
JS下拉框内容左右移动效果的具体实现
2013/07/10 Javascript
JS实现将人民币金额转换为大写的示例代码
2014/02/13 Javascript
使用JavaScript进行进制转换将字符串转换为十进制
2014/09/21 Javascript
jQuery实现设置、移除文本框默认值功能
2015/01/13 Javascript
jQuery插件Skippr实现焦点图幻灯片特效
2015/04/12 Javascript
快速学习jQuery插件 jquery.validate.js表单验证插件使用方法
2015/12/01 Javascript
Node.js+Express配置入门教程
2016/05/19 Javascript
Javascript 5种方法实现过滤删除前后所有空格
2016/06/22 Javascript
Angular中的$watch、$watchGroup、$watchCollection
2017/06/25 Javascript
微信小程序实现图片上传、删除和预览功能的方法
2017/12/18 Javascript
浅谈vue方法内的方法使用this的问题
2018/09/15 Javascript
JS实现的新闻列表自动滚动效果示例
2019/01/30 Javascript
微信小程序如何调用json数据接口并解析
2019/06/29 Javascript
JS工厂模式开发实践案例分析
2019/10/17 Javascript
Node.js API详解之 os模块用法实例分析
2020/05/06 Javascript
详解微信小程序入门从这里出发(登录注册、开发工具、文件及结构介绍)
2020/07/21 Javascript
[48:38]DOTA2亚洲邀请赛 3.31 小组赛 B组 Mineski vs Secret
2018/03/31 DOTA
[55:03]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第二场 11.20
2020/11/20 DOTA
[01:33]完美世界DOTA2联赛PWL S3 集锦第二期
2020/12/21 DOTA
在Python程序中实现分布式进程的教程
2015/04/28 Python
Python获取系统所有进程PID及进程名称的方法示例
2018/05/24 Python
用Python和WordCloud绘制词云的实现方法(内附让字体清晰的秘笈)
2019/01/08 Python
Python之NumPy(axis=0 与axis=1)区分详解
2019/05/27 Python
英语教育专业自荐信
2014/05/29 职场文书
2015年采购部工作总结
2015/04/23 职场文书
使用springboot暴露oracle数据接口的问题
2021/05/07 Oracle