onclick() 和 onblur() 排序问题

2022-08-30 03:00:46

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

  • 当用户单击输入字段之外的任意位置时,应删除该菜单。
  • 更具体地说,如果用户单击菜单内的 div,则应删除该菜单,并应根据单击的 div 进行特殊处理。

这是我的实现:

输入字段有一个事件,每当用户单击输入字段外部时,该事件都会删除菜单(通过将菜单的父级设置为空字符串)。菜单内的 div 也具有执行特殊处理的事件。onblur()innerHTMLonclick()

问题在于,单击菜单时事件永远不会触发,因为输入字段首先触发并删除菜单,包括 s!onclick()onblur()onclick()

我通过将菜单 divs 拆分为和事件并设置鼠标向下的全局标志来解决这个问题,该标志在鼠标向上时清除,类似于此答案中建议的。因为在 之前触发,所以如果单击了其中一个菜单 div,则会设置标志,但如果屏幕上的其他地方被设置,则不会设置该标志。如果菜单被点击,我立即返回而不删除菜单,然后等待触发,此时我可以安全地删除菜单。onclick()onmousedown()onmouseup()onmousedown()onblur()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

我遇到了与您完全相同的问题,我的UI完全按照您的描述进行设计。我通过简单地将菜单项替换为 .我没有做任何其他事情。没有,没有标志。这解决了这个问题,让浏览器根据这些事件处理程序的优先级自动重新排序,而无需我做任何额外的工作。onClickonMouseDownonMouseUp

有什么理由为什么这对你来说不起作用?


答案 2

onClick不应替换为 。onMouseDown

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

举个例子:当不小心点击一个按钮时,用户希望能够按住鼠标点击,将光标拖到元素外面,然后释放鼠标按钮,最终导致没有动作。 这样做。 不允许用户按住鼠标,而是会立即触发操作,而用户没有任何追索权。 是我们期望在计算机上触发操作的标准。onClickonMouseDownonClick

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

毕竟,事件是 和 的组合,当且仅当它们都发生在同一元素中。onClickonMouseDownonMouseUp