最近在开发过程中遇到了一个问题,感觉能够通过监听keydown事件来解决。然而,在实际的过程中发现,我原先对于keydown事件的了解并不是很正确。所以,在具体理解过keydown事件之后,在此做个总结。
本文次要包含以下几个方面的内容:
- 遇到的问题
- keydown事件
- 解决方案
遇到的问题
在开发过程中,我遇到这样一个需要:
当鼠标悬浮在指标dom上的时候,鼠标须要设置成非凡的款式:
- 没有按住ctrl键,鼠标款式设置成款式1;
- 按住ctrl键,鼠标款式设置成款式2。
我的第一想法是,通过监听mousemove事件来判断鼠标是否悬浮在指标dom上。而后通过event.ctrlKey来判断此时是否按住了ctrl键:
- 如果没有按住,解决上述情况1;
- 如果按住了,解决上述情况2。
然而,只监听mousemove事件不能笼罩所有的状况。比方,首先把鼠标挪动到指标dom上,此时鼠标不动,按下或者松开ctrl键,此时鼠标的款式是须要变动的。然而,咱们在按下或者松开ctrl键之后并没有挪动鼠标,所以不会触发mousemove事件。
所以,我就想通过keydown和keyup事件来监听ctrl键的按下和松开事件。
首先,我给指标dom增加了keydown事件。这时,问题就来了:keydown事件基本就没有触发。
而后,我就想试试在body上绑定keydown事件,而后通过判断event.target是否是指标dom来判断鼠标地位。
最初,我发现event.target是body元素,而不是我想要的指标dom。所以,我就开始查找材料,发现keydown事件原来和我设想中的不一样。
keydown事件
通过查阅MDN上的keydown事件,发现该事件有如下限度:
Keyboard events are only generated by <inputs>, <textarea> and anything with the contentEditable attribute or with tabindex="-1".
首先我的指标dom不是input
和textarea
元素,所以就思考增加contentEditable
或者tabindex
属性。
首先,咱们看下contentEditable属性。当把这个元素设置成可编辑之后(不可编辑态不会触发keydown事件),元素的内容就能够像textarea
一样进行编辑了,这个不是我要的性能,所以这种形式不行。
而后,能够设置tabindex="-1"
。此时,在肯定条件下,是能够触发keydown事件的。这个肯定条件就是,首先通过点击操作让指标dom处于focus的状态,此时再按下ctrl键才会触发keydown事件。显然,这种形式也不能满足需要。
此时,咱们先思考一个问题:为什么在第一局部给body增加keydown事件是能够的。咱们已知的信息是:
- keyboard事件触发的条件:非凡元素,contentEditable,tabindex="-1"。
所以,我狐疑body元素设置了tabindex属性:
document.body.tabIndex // -1
果然如此!
后面咱们有说到,只有当dom处于focus状态下的时候,按下ctrl键才会触发keydown事件。那么,对于body元素是不是也是这样的呢?
首先,咱们退出页面的全屏模式,而后点击不属于浏览器的中央。此时,浏览器页面处于失去焦点的状态。
咱们把鼠标从新挪动到页面的内容区域(留神,只是挪动过来,不要点击)。而后,按下ctrl键,你会发现keydown事件同样没有触发。
然而,对于body元素来说,先触发focus事件并不是一个问题。在方才页面失去焦点的状况下,把鼠标挪动到页面上有hover成果的元素上,发现这些元素的hover成果同样不会触发。所以,页面操作的默认前提应该就是页面处于focus状态。这样对于body元素来说,keydown事件触发前首先进行focus操作就不是一个非凡的操作了。
解决方案
通过上述局部的内容,咱们晓得能够监听body元素的keydown事件。那么,接下来的问题就变成了怎么联合body的keydown事件来判断ctrl键按下或者松开的时候,鼠标是否正好在指标dom上。
我是通过监听document元素的mousemove事件来解决的。当mousemove事件触发的时候,把event.target保留在一个全局变量中。当body的keydown事件触发的时候,通过判断这个全局变量是否是指标dom来管制后续逻辑。ctrl键松开的逻辑同理,通过body的keyup事件来监听。
总结
心愿大家能有所播种。如有谬误,欢送留言探讨。