今天有个同事遇到一个奇怪的问题,我照着他的代码做了一些简化写了这个demo

 <!DOCTYPE html>
<html>
<head>
<style type="text/css">
div{position: absolute;top: 0;left: 0;height: 50px}
#back{background-color: blue;left: 20px;width: 200px;z-index: 0}
#front{background-color: green;top:10px;width: 100px;z-index: 1}
</style>
</head>
<body>
<div id="back"></div>
<div id="front"></div>
<script type="text/javascript">
document.getElementById("back").addEventListener("click", function () {
console.log("back clicked");
})
document.getElementById("front").addEventListener("click", function () {
console.log("front clicked");
this.setAttribute("style", "z-index:0");
document.getElementById("back").setAttribute("style", "z-index:1");
})
document.getElementById("back").addEventListener("dblclick", function () {
console.log("back double clicked");
})
document.getElementById("front").addEventListener("dblclick", function () {
console.log("front double clicked");
})
</script>
</body>
</html>

代码的逻辑大致是这样的:

首先,页面中绿色方块为front,蓝色方块为back。系统的需求是,在绿色方块上单击时,切换两个方块覆盖方式(也就是点击front后back会跑到front前面)。同时,还需要在双击蓝色方块时实现另一个功能逻辑。

于是这哥们很自然了写了类似上面的代码就提交了。没多久,测试MM提了一个bug:“双击绿色方块时,不应触发双击蓝色方块的逻辑”。

后来我自己测了一下,果然如测试MM所说,当双击绿色和蓝色方块重叠的区域时,控制台会打印出这样的log:

浏览器会先触发front click,然后是back click,再然后居然是back double click。按理说,在back上面只点击了一次,应该不触发double click才对,毕竟第一次click是在front上触发的。

所以,我大胆猜想,浏览器本身并不会去判定鼠标是否触发双击事件,双击事件是由操作系统直接分发给浏览器的。当浏览器收到操作系统发来的双击消息时,直接根据该双击事件中的坐标去页面中找命中的元素,并在这个元素上触发js中的双击事件。

操作系统在判断是否发生双击时,并不知道第一次click和第二次click的目标不是同一个元素,所以只要两次click的间隔足够短就认为构成双击事件。而浏览器在收到操作系统发来的双击事件时,并没有去检测这次双击是由那两次单击所产生,而是直接根据双击事件的坐标信息将这个事件分发到相应的html元素上了。

为验证这个猜想,我又写了一个demo

 <!DOCTYPE html>
<html>
<head>
<style type="text/css">
body{transition:padding-left 8s linear;padding-left: 0}
div{width: 10px;height: 200px;background-color: blue;display: inline-block;float: left;}
</style>
</head>
<body>
<div id="div_00"></div>
<div id="div_01"></div>
<div id="div_02"></div>
<div id="div_03"></div>
<div id="div_04"></div>
<div id="div_05"></div>
<div id="div_06"></div>
<div id="div_07"></div>
<div id="div_08"></div>
<div id="div_09"></div>
<div id="div_10"></div>
<div id="div_11"></div>
<div id="div_12"></div>
<div id="div_13"></div>
<div id="div_14"></div>
<div id="div_15"></div>
<div id="div_16"></div>
<div id="div_17"></div>
<div id="div_18"></div>
<div id="div_19"></div>
<div id="div_20"></div>
<div id="div_21"></div>
<div id="div_22"></div>
<div id="div_23"></div>
<div id="div_24"></div>
<div id="div_25"></div>
<div id="div_26"></div>
<div id="div_27"></div>
<div id="div_28"></div>
<div id="div_29"></div>
<script type="text/javascript">
var divs = document.getElementsByTagName("div");
for(var i = 0, length = divs.length; i < length; i++){
divs[i].addEventListener("click", function () {
console.log("clicked", this.id);
});
divs[i].addEventListener("dblclick", function () {
console.log("double clicked", this.id);
});
} setTimeout(function(){
document.body.setAttribute("style", "padding-left:300px");
}, 1000);
</script>
</body>
</html>

当页面中的蓝色方块开始移动后,在蓝色方块上双击鼠标,可以多试几次,得到下面的结果:

可以看到,div_26、div_22两次双击事件分别是由div27、div26和div23、div22的两次单击触发的。

从这两个结果来看,确实是符合我的猜想的。

不过,这个demo也带来了一些疑惑:

1、clicked div_19 这个log打印的时候,我非常确定我点击了两次鼠标,但是只打出了这一个log,为什么?

2、double clicked div_15和double clicked div_11这两次双击事件触发前,都只触发了一次click事件,这又是为什么?

以上所有代码测试结果都是基于 Chrome 33 和 IE 11 运行环境。

希望有高人指导,也欢迎大家各抒己见。

如需转载,请注明转自:http://www.cnblogs.com/silenttiger/p/3578397.html

欢迎关注我的微信公众号:老虎的小窝

html元素双击事件触发机制猜想及疑惑的更多相关文章

  1. 【深入浅出Linux网络编程】 “基础 -- 事件触发机制”

    回顾一下“"开篇 -- 知其然,知其所以然"”中的两段代码,第一段虽然只使用1个线程但却也只能处理一个socket,第二段虽然能处理成百上千个socket但却需要创建同等数量的线程 ...

  2. C#事件触发机制

    C#的事件触发机制,类似于c++的回调函数机制 我先简单说一下,委托和事件的实质,后期再重开一篇博文来详细说 委托:指向方法的指针,类似于C的函数指针 事件:是一个可以存放0个或多个方法指针的数据结构 ...

  3. EventEmitter:nodeJs事件触发机制

    Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列 Node.js 里面的许多对象都会分发事件:一个 net.Server 对象会在每次有新连接时触发一个事件, 一个 fs.r ...

  4. [转载] 理解 epoll 的事件触发机制

    原文: http://weibo.com/p/1001603862394207076573?sudaref=weibo.com epoll的I/O事件触发方式有两种模式:ET(Edge Trigger ...

  5. WinForm中的事件触发机制学习

    在一个Form窗体中拖个按钮,双击后系统自动生成代码: private void button1_Click(object sender, EventArgs e) { } 同时在窗体的Initial ...

  6. 当页面加载完成时,JQ触发添加页面的元素的事件触发不了。。

    有下代码可知: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default. ...

  7. Yii中事件触发机制

    控制器初始化中添加事件处理方法,在需要触发的地方直接触发 public function init() { parent::init(); // TODO: Change the autogenera ...

  8. python 模拟事件触发机制

    EventManager.py # -*- encoding: UTF-8 -*- # 系统模块 from queue import Queue, Empty from threading impor ...

  9. JQuery的方便之处——宽高设置、坐标值和滚动条+事件绑定机制

    1.元素的宽高 可以通过css来进行设置,例如:$("元素").css({"宽度":"值","高度":"值&q ...

随机推荐

  1. extends CakeRequest,重写is方法

    背景:Cakephp开发环境版本是2.3.8,服务器的cakephp版本是2.3.5,测试好的代码上传到服务器上后发现总爆如下的警告: Warning (2): strtolower() expect ...

  2. [CentOS7] [VMWARE] 增加磁盘空间后扩大逻辑分区

    Learn to rescan disk in Linux VM when its backed vdisk in vmware is extended. This method does not r ...

  3. jQuery validate插件,自动验证无效的原因及解决方法归纳

    最近在使用validate插件进行验证的时候,出现有的控件在个别事件(比如keydown.foucs.onchange等)下不能自动验证,而有的控件却又正常,当时觉得很诡异,后来仔细测试查看,归纳原因 ...

  4. .NET实现自动编译

    前言 因每次发布版本的时候,都需要打开vs项目,然后进行编译.如果刚好手里有文件在修改,就需要先签入之类的.所以想找个可以实现自动编译的工具. 在网上查询了不少资料,终于基本上实现了自动编译的功能.因 ...

  5. 汇编语言debug命令与指令机器码

    一.debug命令 二.标志信息 -r用这个指令,得到的信息右下角: NV UP EI PL NZ NA PO NC 这些符号代表的就是标志寄存器里常用标志位的值.这个是符号值对应表: 溢出标志OF( ...

  6. IIS中添加MIME类型

    今天上传一个html5后台管理模版的时候,在服务器上预览发现网页加载的远程woff类型的字体不显示,如下图所示: 在本地预览的时候,正常加载字体文件应该是这样的: 利用url访问字体文件的时候提示:该 ...

  7. Mysql表类型(存储引擎)的比较

    面试官问:你知道mysql有哪些存储引擎,区别是啥? 我:一脸闷逼,于是乎下来补一补,以作备查 1.和大多数数据库不同,MySQL 中有一个存储引擎的概念,针对不同的存储需求可以选择最优的存储引擎. ...

  8. python textwrap.md

    textwrap textwrap模块可以用来格式化文本, 使其在某些场合输出更美观. 他提供了一些类似于在很多文本编辑器中都有的段落包装或填充特性的程序功能. Example Data 本节中的示例 ...

  9. 方法(method)和函数(function)的区别

    函数是一段代码,通过名字来进行调用.它能将一些数据(参数)传递进去进行处理,然后返回一些数据(返回值),也可以没有返回值. 所有传递给函数的数据都是显式传递的. 方法也是一段代码,通过一个与对象相关联 ...

  10. Netty入门(七)使用SSL/TLS加密Netty程序

    为了支持 SSL/TLS,Java 提供了 javax.net.ssl API 的类 SslContext 和 SslEngine 使它相对简单的实现解密和加密.Netty 利用该 API 实现了 C ...