onclick()和onblur()排序问题

时间:2013-07-21 04:20:40

标签: javascript onclick onblur

我有一个输入字段,可以显示自定义下拉菜单。我想要以下功能:

  • 当用户点击输入字段外的任何位置时,应删除该菜单。
  • 如果,更具体地说,用户点击菜单中的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;
    ...
}

6 个答案:

答案 0 :(得分:121)

我遇到与你完全相同的问题,我的UI设计与你描述完全一样。我通过简单地用onMouseDown替换菜单项的onClick来解决问题。我什么都没做;没有onMouseUp,没有标志。这解决了这个问题,让浏览器根据这些事件处理程序的优先级自动重新排序,而不需要我做任何额外的工作。

为什么这对你没有用呢?

答案 1 :(得分:10)

onClick不应替换为onMouseDown

虽然这种方法行之有效,但两者在本质上是不同的事件,在用户眼中具有不同的期望。在这种情况下,使用onMouseDown而非onClick会破坏软件的可预测性。因此,这两个事件是不可互换的。

为了说明:用户不小心单击按钮时,希望能够按住鼠标单击,将光标拖到元素外,然后释放鼠标按钮,最终不会采取任何措施。 onClick执行此操作。 onMouseDown不允许用户按住鼠标,而是立即触发操作,而无需用户追索。 onClick是我们期望在计算机上触发操作的标准。

在这种情况下,请在event.preventDefault()事件上调用onMouseDown。默认情况下,onMouseDown默认情况下会导致模糊事件,而在调用preventDefault时不会这样做。然后,onClick将有机会被调用。仅在onClick之后,模糊事件仍然会发生。

毕竟,onClick事件是onMouseDownonMouseUp的组合,只要且仅当它们都出现在同一元素内即可。

答案 2 :(得分:4)

onmousedown替换为onfocus。因此,当焦点位于文本框内时,将触发此事件。

onmouseup替换为onblur。当您从文本框中取出焦点时,onblur将会执行。

我想这就是你可能需要的。

<强>更新

执行onfocus函数时 - >删除将在onblur中应用的类并添加要在onfocus上执行的类

执行onblur函数时 - >删除将在onfocus中应用的类 并添加要在onblur上执行的类

我认为不需要标志变量。

更新2:

您可以使用事件onmouseout和onmouseover

onmouseover - 当光标在它上面时检测。

onmouseout - 当光标离开时检测。

答案 3 :(得分:2)

更优雅(但可能性能较差)的解决方案:

使用document.onclick代替使用输入的onblur删除菜单,而onblur会在input.onclick之后触发。

但是,这也意味着在单击输入时删除菜单,这是不希望的行为。使用event.stopPropagation()设置{{1}},以避免将点击次数传播到文档点击事件。

答案 4 :(得分:0)

通过onfocus更改onclick

即使onblur和onclick不能相处得很好,但显然onfocus和是onblur。因为即使菜单关闭后,onfocus对于单击内部的元素仍然有效。

我做了,但确实有效。

答案 5 :(得分:-3)

您可以在setInterval处理程序中使用onBlur函数,如下所示:

<input id="input" onblur="removeMenu()" ... />

function removeMenu() {
    setInterval(function(){
        if (!mouseflag) {
            document.getElementById('menu').innerHTML = '';
        }
    }, 0);
}

setInterval函数将从调用堆栈中删除onBlur函数,添加因为您将时间设置为0,此函数将在其他事件处理程序完成后立即调用