项目综述

  • 在页面中模拟某操作系统的操作界面,提供应用窗口的最大化、最小化、还原等功能

需求

  • 对一个应用窗口标题栏双击使其铺满整个视口,再次双击还原到原来大小,和位置
  • 部分代码片段如下:
win.addEventListener('dblclick', (event) => {
if (cache && cache.status === 'normal') {
Win.maximize(id);
} else if (cache && cache.status === 'maximize') {
Win.restore(id);
}
});
  • 在Win.restore()和Win.maximize()方法中通过id读取该应用的缓存信息
{
top: app.cache.pos.top,
left: app.cache.pos.left,
width: app.size.width,
height: app.size.height,
}

问题

  • Chrome浏览器(87)

    • 使用电脑自带触摸板进行双击测试,正常
    • 使用鼠标进行双击测试,双击事件触发后cache.pos内的内容丢失,top和left属性不存在,cache中其余属性正常
  • Edge浏览器(87)

    • 表现与Chrome浏览器一致
  • Firefox浏览器(84)

    • 在使用电脑自带触摸板和鼠标测试时,双击事件触发后均出现cache.pos内的内容丢失的情况,其余属性正常

猜想

  • 对象嵌套深度问题???毕竟嵌套最深的丢了,其他的都没事
// 将left和top直接定义在cache,表现与之前测试结果一致,修改无效
{
top: app.cache.top,
left: app.cache.left,
width: app.size.width,
height: app.size.height,
}
  • 命名冲突问题???
// 将属性名加上前缀,表现与之前测试结果一致,修改无效
{
top: app.cache.winTop,
left: app.cache.winLeft,
width: app.size.width,
height: app.size.height,
}
  • 事件冲突问题,该元素同时定义了单击事件,但注释掉单击事件后问题依旧存在

  • 双击事件的BUG????????

// 使用单击事件模拟双击事件,在谷歌和Edge中使用触摸板最大化和还原也会造成数据丢失了
function doubleclick(elem, onsingle, ondouble) {
if (dblFlag) {
dblFlag = true;
setTimeout(function () {
if (dblFlag) {
onsingle(elem);
}
dblFlag = false;
}, 300);
} else {
dblFlag = false;
ondouble(elem);
}
}

解决

  • 就在我已经快要放弃这个功能的时候,发现这个元素还绑定了另外一个事件

  • 为了让窗口可以在页面中自由拖动,加入了mousedown,mousemove,mouseup事件模拟拖拽事件,提前声明变量currentLeft和currentTop,在mousemove时修改两个属性的值,在mouseup时保存当前位置,如下代码:

window.onmouseup = function () {
window.onmousemove = null;
app.cache.pos.left = currentLeft;
app.cache.pos.top = currentTop; return false;
}
  • 在双击事件中连续触发了mouseup和mousedown,所以给top和left写入了新值

但是,双击事件并没有触发到mousemove事件,导致currentLeft和currentTop没有值写入,还是初始的未赋值状态,并将undefined写入了缓存,也就是cache.pos内属性丢失的问题

  • 知道了问题就好解决了,加一个判空就行了
window.onmouseup = function () {
window.onmousemove = null;
app.cache.pos.left = currentLeft || app.cache.pos.left;
app.cache.pos.top = currentTop || app.cache.pos.top; return false;
}
  • 至于使用触摸板和使用鼠标导致差异,大概是用鼠标手比较稳,双击不会出现位置移动,而触摸板两次点击很难都点中同一位置,或多或少有差异,触发mousemove写入了新值
  • 不同浏览器的不同表现,大概是对双击事件中两次点击的误差范围规定不同,改用了单击事件模拟双击事件后,浏览器的表现就一致了

反思

  • 能给初始值就给初始值,不能给初始值在使用的时候一定要给默认值!
  • 别瞎想,看看自己的猜想,连边都没有摸到,在用单击事件模拟双击时就应该联想到其余的事件,然后检查是否相互影响
  • 就自己目前的水平,所有的问题都一定是自己的问题!
  • 自己坑起自己来果然是不遗余力啊!

记一次多事件绑定中自己给自己设置的坑——click,dblclick,mousedown,mousemove,mouseup的更多相关文章

  1. javascript简单拖拽(鼠标事件 mousedown mousemove mouseup)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  2. 关于.net core 在docker中监听地址设置踩坑记

    1.今天在做docker容器的时候发现如果将.net core 内部监听地址设置为localhost:8888. 2.在docker build -p 6444:8888 运行容器后,外部通过6444 ...

  3. jQuery 中的事件绑定

    一.事件概念 和数据库中的触发器一样,当操作了数据的时候会引发对应的触发器程序执行 一样,JS 中的事件就是对用户特定的行为作出相应的响应的过程,其实上就是浏览器 监听到用户的某些行为的时候会执行对应 ...

  4. js实例分析JavaScript中的事件委托和事件绑定

    我们在学习JavaScript中,难免都会去网上查一些资料.也许偶尔就会遇到“事件委托”(也有的称我“事件代理”,这里不评论谁是谁非.以下全部称为“事件委托”),尤其是在查JavaScript的事件处 ...

  5. 深入学习jQuery事件绑定

    × 目录 [1]bind [2]trigger [3]delegate[4]on[5]one 前面的话 javascript有HTML.DOM0级.DOM2级和IE这四种事件处理程序,而jQuery对 ...

  6. jQuery-1.9.1源码分析系列(十) 事件系统——事件绑定

    事件绑定的方式有很多种.使用了jQuery那么原来那种绑定方式(elem.click = function(){...})就不推荐了,原因? 最主要的一个原因是elem.click = fn这种方式只 ...

  7. js事件绑定及深入

    学习要点: 1.传统事件绑定的问题2.W3C事件处理函数3.IE事件处理函数4.事件对象的其他补充 事件绑定分为两种:一种是传统事件绑定(内联模型,脚本模型),一种是现代事件绑定(DOM2级模型).现 ...

  8. JQuery实现click事件绑定与触发方法分析

    原生JS通过什么方法绑定click事件? 原生js有一下三种方法为DOM对象绑定click事件, 第一种,在html中添加 onclick属性,在此属性中添加要绑定的事件函数,如下, 这种方法为htm ...

  9. jQuery三种事件绑定方式.bind(),.live(),.delegate()

    .bind(), .live(), 和 .delegate()之间的区别并不明显.但是理解它们的不同之处有助于写出更简洁的代码,并防止我们的交互程序中出现没有预料到的bug. 基础 DOM树 首先,图 ...

随机推荐

  1. 分布式文件系统HDFS-部署和配置

    1 部署HDFS HDFS的基本操作可以分为集群管理和文件系统操作两种类型: 集群管理:包括Namenodede 的格式化.集群的启动和停止.集群信息查看等. 文件系统:包括对目录.文件和权限等内容的 ...

  2. ⑤SpringCloud 实战:引入Zuul组件,开启网关路由

    这是SpringCloud实战系列中第4篇文章,了解前面第两篇文章更有助于更好理解本文内容: ①SpringCloud 实战:引入Eureka组件,完善服务治理 ②SpringCloud 实战:引入F ...

  3. javascript是面向对象的,怎么体现javascript的继承关系?

    一个简单的例子: var A =function(){ } A.prototype = { v : 5, tmp : 76, echo : function(){console.log(this.tm ...

  4. Tomcat启动报错org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file

    错误: 今天SVN导入新项目后启动项目时控制台报错,之后在网上搜了很多方法.下面列了一些大佬的解决方案: 1. 检查日志配置文件-logging.properties:https://www.cnbl ...

  5. 使用Promise实现红绿灯交替重复亮

    红灯3秒亮一次,黄灯2秒亮一次,绿灯1秒亮一次:如何让三个灯不断交替重复亮灯?(用Promise实现) function red() { console.log('red'); } function ...

  6. 深入解析ConcurrentHashMap:感受并发编程智慧

    如果有一个整型变量count,多个线程并发让count自增1,你会怎么设计? 你知道如何让多个线程协作完成一件事件吗? 前言 很高兴遇见你~ ConcurrentHashMap是个老生常谈的集合类了, ...

  7. sql注入之union注入

    联合查询注入利用的前提: 必须要有回显 联合查询过程: 判断是否存在注入点 判断是什么类型注入(字符型or数字型) 判断闭合方式 查询列数个数(order by) 5, 获得数据库名 获得表名 获得字 ...

  8. Sentinel Dashboard(基于1.8.1)流控规则持久化到Nacos——涉及部分Sentinel Dashboard源码改造

    前言 之前虽然也一直在使用sentinel实现限流熔断功能,但却没有好好整理之前看的源码与资料,今天有时间将之前自己整理过的资料写成一篇博文,或者是是一篇关于Sentinel(基于目前最近版本1.8, ...

  9. vue第八单元(组件通信 子父,父子组件通信 自定义事件 事件修饰符 v-model props验证 )

    第八单元(组件通信 子父,父子组件通信 自定义事件 事件修饰符 v-model props验证 ) #课程目标 掌握使用props让父组件给子组件传参(重点) 掌握props属性的使用以及prop验证 ...

  10. 开源OLAP引擎对比

    什么是olap 01.绝大多数请求都是读请求 02.数据以相当大的批次(>1000行)更新,而不是单行更新;或者它根本没有更新 03.数据已添加到数据库,但不会进行修改 04.对于读取,每次查询 ...