onclick() 和 onblur() 排序问题
Posted
技术标签:
【中文标题】onclick() 和 onblur() 排序问题【英文标题】:onclick() and onblur() ordering issue 【发布时间】:2013-07-20 02:12:13 【问题描述】:我有一个输入字段,它会显示一个自定义下拉菜单。我想要以下功能:
当用户点击输入字段外的任意位置时,菜单应被移除。 更具体地说,如果用户单击菜单内的 div,则应删除该菜单,并且应根据单击的 div 进行特殊处理。这是我的实现:
输入字段有一个onblur()
事件,当用户在输入字段外单击时删除菜单(通过将其父级的innerhtml
设置为空字符串)。菜单中的 div 也有onclick()
事件执行特殊处理。
问题是onclick()
事件在单击菜单时永远不会触发,因为输入字段的onblur()
首先触发并删除菜单,包括onclick()
s!
我通过将菜单 div 的 onclick()
拆分为 onmousedown()
和 onmouseup()
事件并在鼠标按下时设置一个全局标志来解决问题,该标志在鼠标抬起时被清除,类似于 this answer 中的建议。因为onmousedown()
在onblur()
之前触发,所以如果单击了其中一个菜单div,则该标志将设置在onblur()
中,但如果屏幕上的其他位置被单击,则不会。如果菜单被点击,我会立即从onblur()
返回而不删除菜单,然后等待onclick()
触发,此时我可以安全地删除菜单。
有没有更优雅的解决方案?
代码如下所示:
<div class="menu" onmousedown="setFlag()" onmouseup="doProcessing()">...</div>
<input id="input" onblur="removeMenu()" ... />
var mouseflag;
function setFlag()
mouseflag = true;
function removeMenu()
if (!mouseflag)
document.getElementById('menu').innerHTML = '';
function doProcessing(id, name)
mouseflag = false;
...
【问题讨论】:
【参考方案1】:onClick
不应替换为 onMouseDown
。
虽然这种方法有些工作,但两者是根本不同的事件,在用户眼中具有不同的期望。在这种情况下,使用onMouseDown
而不是onClick
会破坏软件的可预测性。因此,这两个事件是不可互换的。
举例说明:当不小心点击一个按钮时,用户期望能够按住鼠标点击,将光标拖到元素外,然后松开鼠标按钮,最终导致没有动作。 onClick
这样做。 onMouseDown
不允许用户按住鼠标不放,而是会立即触发一个动作,对用户没有任何追索权。 onClick
是我们期望在计算机上触发操作的标准。
在这种情况下,请在 onMouseDown
事件上调用 event.preventDefault()
。 onMouseDown
默认会引发模糊事件,在调用preventDefault
时不会这样做。然后,onClick
将有机会被调用。模糊事件仍然会发生,只是在onClick
之后。
毕竟,onClick
事件是 onMouseDown
和 onMouseUp
的组合,当且仅当它们都出现在同一个元素中。
【讨论】:
这对我来说是完美的解决方案,评论完全正确 - 替换 onMouseDown 会混淆用户体验。投了赞成票。 这应该是正确的答案。感谢您发布此内容 值得注意的是,这也有一些轻微的副作用,例如。无法通过在元素内单击来选择文本。想不出有太多这样的问题,就是觉得有点好笑。 如果我在onMouseDown
事件上使用event.preventDefault()
,则不会调用我的onFocus
事件
焦点位置在许多应用程序中都很重要。标记的解决方案不允许通过回调将焦点恢复到初始输入框。 onBlur 将发生并移除焦点。这个使用event.preventDefault()
的实现确实允许onClick
处理程序将焦点设置到文本框。【参考方案2】:
我遇到了和你一样的问题,我的 UI 完全按照你的描述设计。我通过简单地将菜单项的onClick
替换为onMouseDown
解决了这个问题。我什么也没做;没有onMouseUp
,没有标志。这解决了这个问题,让浏览器根据这些事件处理程序的优先级自动重新排序,而无需我做任何额外的工作。
有什么理由说明这对你不起作用?
【讨论】:
这确实有效。我已经在 FF 中对其进行了测试,效果非常好。 它有效。看起来onmousedown
在 onblur
之前执行,在 Firefox、Chrome 和 Internet Explorer 中测试。
值得注意的是,这确实会自然地改变行为 - 然后在鼠标按下而不是鼠标向上时处理点击交互。对于大多数人来说可能很好(在这种情况下包括自我),但也有一些缺点。最值得注意的是,如果我单击错误,我经常单击然后拖动按钮,这会阻止调用 onclick - 如果按钮执行非纯功能(删除、发布等),您可能希望保留它并使用标志方法。
在你设置 mouseDown 而不是 onClick 的那一刻,可访问性怎么样,你会杀死所有
@ian-macfarlane 下面列出的答案是处理此问题的正确方法。总之...onMouseDown
和 event.preventDefault()
和 onClick
以及您想要的操作。【参考方案3】:
通过 onfocus 改变 onclick
即使onblur和onclick相处得不是很好,但显然onfocus和yes onblur。因为即使在菜单关闭后,onfocus 仍然对内部单击的元素有效。
我做到了,它奏效了。
【讨论】:
【参考方案4】:您可以在 onBlur
处理程序中使用 setInterval
函数,如下所示:
<input id="input" onblur="removeMenu()" ... />
function removeMenu()
setInterval(function()
if (!mouseflag)
document.getElementById('menu').innerHTML = '';
, 0);
setInterval
函数将从调用堆栈中删除您的 onBlur
函数,添加因为您将时间设置为 0,此函数将在其他事件处理程序完成后立即调用
【讨论】:
setInterval
是个坏主意,您永远不会取消它,因此它将不断运行您的功能,并且很可能导致您的网站使用最大 cpu。如果您打算使用这种技术(我不推荐),请改用setTimeout
。让您的应用依赖于某些事件的发生时间是有风险的事情。
鲁滨逊会有危险!危险!未来的比赛条件!
我最初想出了这个解决方案(好吧setTimeout
不是setInterval
),但我不得不将它提高到250
ms,然后才能以正确的顺序发生。这个错误可能仍然存在于速度较慢的设备上,并且它也会使延迟明显。我尝试了onMouseDown
,它工作正常。我想知道它是否也需要触摸事件。
如果你真的想使用onClick,像间隔这样的东西也不错。但是你想要一个带有条件而不是间隔的递归超时,这样它就不会永远运行。这与 Selenium 条件等待使用的模式相同。【参考方案5】:
将onmousedown
替换为onfocus
。所以当焦点在文本框内时会触发这个事件。
将onmouseup
替换为onblur
。当您将焦点移出文本框时,onblur 就会执行。
我想这就是你可能需要的。
更新:
当你在 onfocus 上执行你的函数时——>移除你将在 onblur 中应用的类并添加你想要在 onfocus 上执行的类
和
当你执行你的函数 onblur-->删除你将在 onfocus 中应用的类 并添加要在 onblur 上执行的类
我认为不需要标志变量。
更新 2:
您可以使用事件 onmouseout 和 onmouseover
onmouseover - 检测光标何时在其上方。
onmouseout-检测光标何时离开。
【讨论】:
为了清楚起见,我已经编辑了我的问题。该解决方案如何避免设置标志的需要?另外,我在菜单上使用onmousedown()
和onmouseup()
,而不是文本框/输入字段。
我还不能接受这个答案,因为我不知道它是否正确。您能否回应我在上述评论中提出的担忧?
当然,我可以看到你如何使用 onmouseover 和 onmouseout 类似于我目前正在做的事情,当鼠标悬停在菜单上时设置一个标志。但是,我仍然认为您需要在 onmouseover 中设置一个标志,该标志在 onmouseout 中被清除,以便您在单击时知道您是否在菜单上方。你能想出一种不需要设置标志的方法吗?
我能看到你的代码吗...把它放在小提琴里...只要把相关的部分和它完全可以,如果我没有看到结果..只是代码..
让我们continue this discussion in chat以上是关于onclick() 和 onblur() 排序问题的主要内容,如果未能解决你的问题,请参考以下文章
React - 带有 onBlur 事件的 ul 阻止 onClick 在 li 上触发
064_Js常用的五大事件 onclick nochanger onload onsubmit onblur
解决input中智能提示框onblur与onclick冲突的问题
事件(Event)(onclick,onchange,onload,onunload,onfocus,onblur,onselect,onmuse)转载
JavaScript 中的事件onload 加载完成事件-onclick 单击事件-onblur 失去焦点事件-onchange 内容发生改变事件-onsubmit 表单提交事件