快速解决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 自定义CircleAnimation,Animate方法学习笔记
Jul 10 Javascript
跨浏览器通用、可重用的选项卡tab切换js代码
Sep 20 Javascript
js加载读取内容及显示与隐藏div示例
Feb 13 Javascript
jquery实现相册一下滑动两次的方法
Feb 09 Javascript
jQuery实现dialog设置focus焦点的方法
Jun 10 Javascript
详解JavaScript的变量和数据类型
Nov 27 Javascript
js文件中直接alert()中文出来的是乱码的解决方法
Nov 01 Javascript
jQuery快速高效制作网页交互特效
Feb 24 Javascript
jQuery插件MovingBoxes实现左右滑动中间放大图片效果
Feb 28 Javascript
JavaScript伪数组用法实例分析
Dec 22 Javascript
微信小程序实现横向滚动导航栏效果
Dec 12 Javascript
深入了解JS之作用域和闭包
Jun 16 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
珊瑚虫IP库浅析
2007/02/15 PHP
php中DOMElement操作xml文档实例演示
2013/03/26 PHP
PHP实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
php判断并删除空目录及空子目录的方法
2015/02/11 PHP
分享10段PHP常用代码
2015/11/11 PHP
CI框架实现创建自定义类库的方法
2018/12/25 PHP
Prototype使用指南之form.js
2007/01/10 Javascript
[原创]js与自动伸缩图片 自动缩小图片的多浏览器兼容的方法总结
2007/03/12 Javascript
jquery实现兼容浏览器的图片上传本地预览功能
2013/10/14 Javascript
jquery 实现两Select 标签项互调示例代码
2014/09/25 Javascript
基于jquery实现图片相关操作(重绘、获取尺寸、调整大小、缩放)
2015/12/25 Javascript
js创建数组的简单方法
2016/07/27 Javascript
Angular.js中用ng-repeat-start实现自定义显示
2016/10/18 Javascript
JS产生随机数的用法小结
2016/12/10 Javascript
jQuery时间验证和转换为标准格式的时间格式
2017/03/06 Javascript
webpack+vue中使用别名路径引用静态图片地址
2017/11/20 Javascript
详解Vue-cli中的静态资源管理(src/assets和static/的区别)
2018/06/19 Javascript
在Django框架中设置语言偏好的教程
2015/07/27 Python
Python使用MD5加密算法对字符串进行加密操作示例
2018/03/30 Python
python批量修改文件编码格式的方法
2018/05/31 Python
浅谈django三种缓存模式的使用及注意点
2018/09/30 Python
Python List列表对象内置方法实例详解
2019/10/22 Python
使用Django搭建一个基金模拟交易系统教程
2019/11/18 Python
Python3 集合set入门基础
2020/02/10 Python
Python 代码调试技巧示例代码
2020/08/11 Python
基于Python实现粒子滤波效果
2020/12/01 Python
python 使用csv模块读写csv格式文件的示例
2020/12/02 Python
python 通过pip freeze、dowload打离线包及自动安装的过程详解(适用于保密的离线环境
2020/12/14 Python
canvas画图被放大且模糊的解决方法
2020/08/11 HTML / CSS
关于Java finally的面试题
2016/04/27 面试题
工业学校毕业生自荐书
2014/01/03 职场文书
火锅店创业计划书范文
2014/02/02 职场文书
局机关干部群众路线个人对照检查材料思想汇报
2014/10/05 职场文书
搭讪开场白台词大全
2015/05/28 职场文书
2016三严三实专题教育活动心得体会
2016/01/06 职场文书
创业计划书之美甲店
2019/09/20 职场文书