Javascript blur与click冲突解决办法


Posted in Javascript onJanuary 09, 2017

解决blur与click冲突

前言:

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

一、blur和click事件简述

  1. blur事件:当元素失去焦点时触发blur事件;其为表单事件,blur和focus事件不会冒泡,其他表单事件都可以。
  2. 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);

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
jQuery 判断页面元素是否存在的代码
Aug 14 Javascript
关于IE中getElementsByClassName不能用的问题解决方法
Aug 26 Javascript
jQuery实现的纵向下拉菜单实例详解【附demo源码下载】
Jul 09 Javascript
JS button按钮实现submit按钮提交效果
Nov 01 Javascript
bootstrap使用validate实现简单校验功能
Dec 02 Javascript
Ajax验证用户名或昵称是否已被注册
Apr 05 Javascript
详解axios在vue中的简单配置与使用
May 10 Javascript
React教程之封装一个Portal可复用组件的方法
Jan 02 Javascript
JavaScript复制内容到剪贴板的两种常用方法
Feb 27 Javascript
node实现生成带参数的小程序二维码并保存到本地功能示例
Dec 05 Javascript
js+canvas实现五子棋小游戏
Aug 02 Javascript
CocosCreator入门教程之网络通信
Apr 16 Javascript
简单实现jQuery级联菜单
Jan 09 #Javascript
prototype与__proto__区别详细介绍
Jan 09 #Javascript
jQuery实现二维码扫描功能
Jan 09 #Javascript
详解Jquery 遍历数组之$().each方法与$.each()方法介绍
Jan 09 #Javascript
详解js产生对象的3种基本方式(工厂模式,构造函数模式,原型模式)
Jan 09 #Javascript
基于jQuery实现滚动刷新效果
Jan 09 #Javascript
用jQuery实现优酷首页轮播图
Jan 09 #Javascript
You might like
php实现的mongodb操作类实例
2015/04/03 PHP
四个常见html网页乱码问题及解决办法
2015/09/08 PHP
PHP设计模式之装饰器模式实例详解
2018/02/07 PHP
Laravel 自动生成验证的实例讲解:login / logout
2019/10/14 PHP
PHP+ajax实现上传、删除、修改单张图片及后台处理逻辑操作详解
2020/02/12 PHP
Firefox div高度自适应
2009/04/28 Javascript
File, FileReader 和 Ajax 文件上传实例分析(php)
2011/04/27 Javascript
Javascript WebSocket使用实例介绍(简明入门教程)
2014/04/16 Javascript
让checkbox不选中即将选中的checkbox不选中
2014/07/11 Javascript
完美实现仿QQ空间评论回复特效
2015/05/06 Javascript
javascript获取网页宽高方法汇总
2015/07/19 Javascript
实现easyui的datagrid导出为excel的示例代码
2016/11/10 Javascript
基于MVC方式实现三级联动(JavaScript)
2017/01/23 Javascript
DVA框架统一处理所有页面的loading状态
2017/08/25 Javascript
微信小程序报错:this.setData is not a function的解决办法
2017/09/27 Javascript
three.js加载obj模型的实例代码
2017/11/10 Javascript
jQuery实现的鼠标响应缓冲动画效果示例
2018/02/13 jQuery
JS实现访问DOM对象指定节点的方法示例
2018/04/04 Javascript
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
animate.css在vue项目中的使用教程
2018/08/05 Javascript
解决layer.prompt无效的问题
2019/09/24 Javascript
[51:14]LGD vs VP 2018国际邀请赛淘汰赛BO3 第一场 8.21
2018/08/22 DOTA
python实现录音小程序
2020/10/26 Python
Python使用pyserial进行串口通信的实例
2019/07/02 Python
Python 类的私有属性和私有方法实例分析
2019/09/29 Python
Django 再谈一谈json序列化
2020/03/16 Python
美国滑雪和滑雪板商店:Buckman
2018/03/03 全球购物
Helly Hansen工作服美国官方网上商店:为最恶劣的环境
2019/09/04 全球购物
介绍一下MYSQL常用的优化技巧
2012/10/25 面试题
师范生自荐信范文
2013/10/06 职场文书
数据员岗位职责
2013/11/19 职场文书
乡镇消防安全责任书
2014/07/23 职场文书
工作收入住址证明
2014/10/28 职场文书
礼貌问候语大全
2015/11/10 职场文书
学校运动会开幕词
2016/03/03 职场文书
合作意向书范本
2019/04/17 职场文书